2

I am attempting to return a dynamically declared array from a function; thus far I am returning a structure to hold a pointer to the memory block that malloc() assigned for the array AND an integer to store the length of the array.


This made me wonder; How does the C Compiler(or whatever) handle an automatic array declared in a program? eg.

main()
{
    //delcare an array holding 3 elements
    int array[] = {1,2,3};


    /*variable to hold length of array
     *size of array / size of 1st element in the array == length of the array
     *this will == 3
     */ 
    int array_Length = (sizeof(array))/(sizeof(*array));


    //call malloc for a block of memory to hold 3 integers(worth of memory)
    int* ptr = malloc(3*(sizeof(int)));


    /*not exactly sure what this formula means when using a pointer???
     *but it seems to always == 1
     */
    int dynamic_array_length = (sizeof(ptr))/(sizeof(*ptr));

    return 0;
}

My point is, the sizeof() operator somehow knows that the automatically declared array has 3 integers within it.

Or more generally:

sizeof(array)

where array is (N x type_size)

N is the number of elements within the array

type_size is the number of bytes of memory used to store the data type


Are automatic arrays stored with additional information about their size/length?

Are dynamic arrays stored differently? (I know that we control when a dynamic variable is freed from memory)

carl13
  • 69
  • 1
  • 1
  • 7
  • Maybe there is a reason a **pointer** is called "pointer" and not "array"? `ptr` is not an array! – too honest for this site Feb 10 '16 at 02:00
  • Quick tip: using `int array_Length = sizeof(array) / sizeof(array[0]);` instead of your version makes this line slightly more readable. – jigglypuff Feb 10 '16 at 02:21
  • The compiler pretty much just looks ahead, counts how many elements there are, and pretends you wrote `int array[actual number of elements goes here];` – user253751 Feb 10 '16 at 02:58

5 Answers5

6

Operator sizeof is a compile-time construct (with the exception of VLA arguments). It tells you the object size in bytes because it knows the exact compile-time object type. And when you know the exact type the size is also immediately known. There's no need to separately store the number of elements anywhere.

Your declaration

int array[] = {1,2,3};

is equivalent to

int array[3] = {1,2,3};

meaning that array has type int[3]. So your sizeof(array) is interpreted as sizeof(int[3]), which is immediately known to the compiler.

sizeof does not know and does not care about any "dynamic arrays" of yours. All it cares about is that in sizeof(ptr) operator sizeof is applied to a pointer. So it evaluates to pointer size.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
2

sizeof(...) is not a function call. It doesn't actually execute at runtime - that value is replaced at the compile time, so what's actually compiled is:

int array_length = 3;

The calculation of dynamic_array_length is incorrect. You divide the size of a pointer by the size of int. Which in your case happens to be the same and get 1 as a result.

Your dynamic array is stored differently - the pointer (on the stack) is separate from the data (on the heap). The first array is just data on the stack - the memory address is constant (for that stack frame) and gets used where needed.

viraptor
  • 33,322
  • 10
  • 107
  • 191
  • Actually `sizeof` is an operator like `+` or `[]`. And an array is not a pointer. – too honest for this site Feb 10 '16 at 02:02
  • @Olaf I'm not disagreeing on either of those points. Did you intend it for other answer? – viraptor Feb 10 '16 at 03:08
  • The first sentence was just to clarify (although it is not always compile-time evaluated). The second refers to "The first **array** is just data on the stack - the **pointer** is constant" - which clearly implies an array is just a constant pointer. – too honest for this site Feb 10 '16 at 03:10
  • @Olaf Ah, I see what you mean. I used pointer in a sloppy way - didn't mean it as a type, but rather a value. Corrected in the answer now. – viraptor Feb 10 '16 at 03:28
1

Disregarding VLAs, the array size of an automatic array is a fact completely known at compile time, and is actually a part of the type of the variable. sizeof is a query (resolved at compile time) to the type system, which is a thing that exists only in the compiler internal data structures while it is compiling. The result is the actual variable size, which is treated essentially as if it was directly written in the source code.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
0

Things about sizeof has been discussed enough, and we know it is a compile-time action.

But in fact, It is true that there is something about size is stored and used in run-time for dynamic variables. Otherwise the free can not do its work correctly.

Here is a good reference: how-do-malloc-and-free-work

Community
  • 1
  • 1
Holsety
  • 103
  • 7
0

You are hitting one of the inconsistencies of C. An array is just a pointer, except where it has been declared. The result of sizeof (somearray) is different, depending upon whether or not sizeof is used in the function defining somearray. In, C, as soon as you move away from the definition, there is no knowledge of anything other than the type of object in the array. That is just one of the many reasons why C programming is so error prone.

Most programming languages other than C or those derived from C, maintain an array descriptor that includes the number of dimensions, the number of elements, and, in some cases, the array bounds.

In the case of dynamic arrays, the library adds overhead, usually before, to the memory returned (sometimes additional overhead is added at the end). This is used so that library can know how much memory is freed.

user3344003
  • 20,574
  • 3
  • 26
  • 62