kartikeykant18
kartikeykant18

Reputation: 1811

Can malloc() be used to define the size of an array?

Here consider the following sample of code:

int *a = malloc(sizeof(int) * n);

Can this code be used to define an array a containing n integers?

Upvotes: 3

Views: 10737

Answers (5)

supercat
supercat

Reputation: 81105

In the language the Standard was written to describe (as distinct from the language that would be described by a pedantic literal reading of it), the intention was that malloc(n) would return a pointer that would, if cast to a T*, could be treated as a pointer to the first element of a T[n/sizeof T*]. Per N1570 7.22.3:

The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated).

The definition of pointer addition and subtraction, however, do not speak of acting upon pointers that are "suitably aligned" to allow access to arrays of objects, but rather speak of pointers to elements of actual array objects. If a program accesses space for 20 int objects, I don't think the Standard does actually says that the resulting pointer would behave in all respects as though it were a pointer to element [0] of an int[20], as distinct from e.g. a pointer to element [0][0] of an int[4][5]. An implementation would have to be really obtuse not to allow it to be used as either, of course, but I don't think the Standard actually requires such treatment.

Upvotes: 0

davmac
davmac

Reputation: 20631

Interpreting your question very literally, the answer is No: To "define an array" means something quite specific; an array definition looks something like:

int a[10];

Whereas what you have posted is a memory allocation. It allocates a space suitable for holding an array of 10 int values, and stores a pointer to the first element within this space - but it doesn't define an array; it allocates one.

With that said, you can use the array element access operator, [], in either case. For instance the following code snippets are legal:

int a[10];
for (int i = 0; i < 10; i++) a[i] = 0;

and

int *a = malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) a[i] = 0;

There is a subtle difference between what they do however. The first defines an array, and sets all its elements to 0. The second allocates storage which can hold an equivalently-typed array value, and uses it for this purpose by initialising each element to 0.

It is worth pointing out that the second example does not check for an allocation error, which is generally considered bad practice. Also, it constitutes a potential memory leak if the allocated storage is not later freed.

Upvotes: 3

Keith Thompson
Keith Thompson

Reputation: 263217

int *a = malloc(sizeof(int) * n);

Can this code be used to define an array a containing n integers?

That depends on what you mean by "define an array".

A declaration like:

int arr[10];

defines a named array object. Your pointer declaration and initialization does not.

However, the malloc call (if it succeeds and returns a non-NULL result, and if n > 0) will create an anonymous array object at run time.

But it does not "define an array a". a is the name of a pointer object. Given that the malloc call succeeds, a will point to the initial element of an array object, but it is not itself an array.

Note that, since the array object is anonymous, there's nothing to which you can apply sizeof, and no way to retrieve the size of the array object from the pointer. If you need to know how big the array is, you'll need to keep track of it yourself.

(Some of the comments suggest that the malloc call allocates memory that can hold n integer objects, but not an array. If that were the case, then you wouldn't be able to access the elements of the created array object. See N1570 6.5.6p8 for the definition of pointer addition, and 7.22.3p1 for the description of how a malloc call can create an accessible array.)

Upvotes: 7

giusti
giusti

Reputation: 3538

Yes. That is exactly what malloc() does.

The important distinction is that

int array[10];

declares array as an array object with enough room for 10 integers. In contrast, the following:

int *pointer;

declares pointer as a single pointer object.

It is important to distiguinsh that one of them is a pointer and that the other as an actual array, and that arrays and pointers are closely related but are different things. However, saying that there is no array in the following is also incorrect:

pointer = malloc(sizeof (int) * 10);

Because what this piece of code does is precisely to allocate an array object with room for 10 integers. The pointer pointer contains the address of the first element of that array.(C99 draft, section 7.20.3 "Memory management functions")

Upvotes: 4

P.P
P.P

Reputation: 121357

int *a = malloc(sizeof(int) * n);

Assuming malloc() call succeeds, you can use the pointer a like an array using the array notation (e.g. a[0] = 5;). But a is not an array itself; it's just a pointer to an int (and it may be a block of memory which can store multiple ints).

Your comment

But I can use an array a in my program with no declaration otherwise

suggests this is what you are mainly asking about.

In C language,

p[i] == *(p + i) == *(i + p) == i[p]

as long as one of i or p is of pointer type (p can an array as well -- as it'd be converted into a pointer in any expression). Hence, you'd able to index a like you'd access an array. But a is actually a pointer.

Upvotes: 5

Related Questions