• Uncategorized

About c : Getting-array-size-in-C-Cannot-understand-output

Question Detail

I am curious why I am getting the following behaviour in my code.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
    int M=24;
    int arr[M];
    int N=24;
    int* ptr=(int*) malloc(sizeof(int)*N); /*Allocate memory of size N  */

    printf("Size of your malloced array is %lu\n",sizeof(ptr)/sizeof(ptr[0])); /* Get the size of memory alloctaed. Should be the same as N?*/

    printf ("Size of your normal arrays is %lu\n",sizeof(arr)/sizeof(arr[0])); /* Ditto  */


    return 0;

The output is

Size of your malloced array is 2
Size of your normal arrays is 24

I would have thought the output would be 24 in both places. How then does one get the size of the malloced array If somehow I have “forgotten” it?

Surely the pointer ptr will contain some information about the size of the malloced array since when we call free(ptr) it will release the array just malloced

Question Answer

When you use sizeof() on a pointer, you get the size of the pointer. Not the size of the allocated array. In your case, a pointer is probably 8 bytes and an int is 4 bytes, hence why you get 2.

In short, you can’t get the size of an allocated array. You need to keep track of it yourself.

EDIT : Note that some compilers do actually support this functionality as an extension:

For example, MSVC supports _msize(): http://msdn.microsoft.com/en-us/library/z2s077bc.aspx

While sizeof() works as you’d expect with fixed-length and variable-length arrays, it doesn’t know anything about the sizes of malloc()‘ed arrays.

When applied to a pointer, sizeof() simply returns the size of the pointer.

More generally, given a pointer to a malloc()‘ed block, there’s no standard way to discover the size of that block.

See C FAQ questions 7.27 and 7.28.

In summary, if you need to know the size of a heap-allocated array in a portable manner, you have to keep track of that size yourself.

You cannot obtain, at runtime, the size of an array if you only have a pointer to (the first element of) the array. There are no constructs at all in C that allow you to do this. You have to keep track of the length yourself.

If you happen to have an array rather than a pointer then you can find its length, but not for a pointer to an element of the array.

In your code, ptr is a pointer and so you cannot find out the length of the array to which it points. On the other hand, arr is an array and so you can find out its length with sizeof(arr)/sizeof(arr[0]).

As this other question points out, there is no portable way getting the size of a dynamic array, since malloc may allocate more memory than requested. Furthermore managing malloc requests is up to the operating system. For instance *nix would calls sbrkand store the requests somewhere. So, when you call sizeof(ptr) it returns the size of the pointer and not the size of the array. On the other hand, if your array is fixed, the size of it is determined at compile time, so the compiler is able to replace sizeof(arr) with the size of the fixed array, thus providing you the “correct” size.

The size of a pointer is 4 bytes on 32-bit machines and 8 bytes on 64-bit machines. I guess you work on a 64-bit machine since the size of an int is 4, and you got that sizeof(ptr)/sizeof(ptr[0]) is 2.

The thing to remember about sizeof is that it is a compile-time operator1; it returns the number of bytes based on the type of the operand.

The type of arr is int [24], so sizeof arr will evaluate to the number of bytes required to store 24 int values. The type of ptr is int *, so sizeof ptr will evaluate to the number of bytes required to store a single int * value. Since this happens at compile time, there’s no way for sizeof to know what block of memory ptr is pointing to or how large it is.

In general, you cannot determine how large a chunk of memory a pointer points to based on the pointer value itself; that information must be tracked separately.

Stylistic nit: a preferred way to write the malloc call is

int *ptr = malloc(sizeof *ptr * N);

In C, you do not need to cast the result of malloc to the target pointer type2, and doing so can potentially mask a useful diagnostic if you forget to include stdlib.h or otherwise don’t have a prototype for malloc in scope.

Secondly, notice that I pass the expression *ptr as the operand to sizeof rather than (int). This minimizes bugs in the event you change the type of ptr but forget to change the type in the corresponding malloc call. This works because sizeof doesn’t attempt to evaluate the operand (meaning it doesn’t attempt to dereference ptr); it only computes its type.

1 The exception to this rule occurs when sizeof is applied to a variable-length array; since the size of the array isn’t determined until runtime, a sizeof operator applied to a VLA will be evaluated at runtime.

2 Note that this is not the case in C++; a cast is required, but if you’re writing C++ you should be using new and delete instead of malloc and free anyway. Also, this is only true since C89; older versions of C had malloc return char * instead of void *, so for those versions the cast was required. Unless you are working on a very old implementation (such as an old VAX mini running an ancient version of VMS), this shouldn’t be an issue.

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.