19

I have codes as following:

main() {
    int array[5] = {3,6,9,-8,1};
    printf("the size of the array is %d\n", sizeof(array));
    printf("the address of array is %p\n", array);
    printf("the address of array is %p\n", &array);
    int * x = array;
    printf("the address of x is %p\n", x);
    printf("the size of x is %d\n", sizeof(x));
}

The output is

the size of the array is 20
the address of array is 0x7fff02309560
the address of array is 0x7fff02309560
the address of x is 0x7fff02309560
the size of x is 8

I know the variable array will be seen as a pointer to the first element of the array, so I understand the the size of x is 8. But I don't know why the size of the array is 20. Isn't it should be 8 (in a 64-bits machine)?

Besides how does the program know that it is 20? As far as I know in C it doesn't store the number of elements. How come the sizeof(array) and sizeof(x) is different? I tracked several posts pertaining to array decaying but no idea on this problem.

Marcus Thornton
  • 5,955
  • 7
  • 48
  • 50
  • 7
    The compiler knows how big the array elements are, and how many elements are in the array, so it can multiply the two to give the result from `sizeof`. It is the compiler's job to know this. – Jonathan Leffler Dec 17 '14 at 04:20
  • Related: [How do I use arrays in C++?](http://stackoverflow.com/a/4810668) The first 3 topics of the accepted answer explain the difference between pointers and arrays pretty extensively. – AliciaBytes Dec 17 '14 at 04:27
  • Check this question http://stackoverflow.com/questions/17752978/exception-to-array-not-decaying-into-a-pointer – nj-ath Dec 17 '14 at 04:36
  • 7
    An array is *not* a pointer to its first element - it just gets automatically converted to one sometimes. – user253751 Dec 17 '14 at 08:33
  • 3
    Key point you might have missed: despite its appearance, `sizeof` is not a function but a compile-time operator. Only the compiler needs to know the answer, so it doesn't matter that the information is not "stored" in the program. – Euro Micelli Dec 17 '14 at 11:27
  • This question would be a lot more interesting if you had asked about VLAs. – user541686 Dec 17 '14 at 12:13
  • @Mehrdad Does variable-length array make any difference in this topic? – Marcus Thornton Dec 17 '14 at 12:37
  • @Mehrdad Which question is the duplication to this one? – Marcus Thornton Dec 17 '14 at 12:38

7 Answers7

20

The name of an array decays to a pointer to the first element of the array in most situations. There are a couple of exceptions to that rule though. The two most important are when the array name is used as the operand of either the sizeof operator or the address-of operator (&). In these cases, the name of the array remains an identifier for the array as a whole.

For a non-VLA array, this means that the size of the array can be determined statically (at compile time) and the result of the expression will be the size of the array (in bytes), not the size of a pointer.

When you take the address of the array, you get the same value (i.e., the same address) as if you'd just used the name of the array without taking the address. The type is different though--when you explicitly take the address, what you get is a pointer of type "pointer to array of N items of type T". That means (for one example) that while array+1 points to the second element of the array, &array+1 points to another array just past the end of the entire array.

Assuming an array of at least two items, *(array+1) will refer to the second element of the array. Regardless of the array size, &array+1 will yield an address past the end of the array, so attempting to dereference that address gives undefined behavior.

In your case, given that the size of the array is 20, and the size of one element of the array is 4, if array was, say, 0x1000, then array+1 would be 0x1004 and &array+1 would be 0x1014 (0x14 = 20).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
15

Your array has a static length so it can be determined at compile time. Your compiler knows the sizeof(int) = 4 and your static array length [5]. 4 * 5 = 20

Edit: Your compilers int is probably 32-bit, but addressing 64-bit. That is why sizeof(pointer) returns 8.

BoJack Horseman
  • 4,406
  • 13
  • 38
  • 70
Raipe
  • 153
  • 7
11

Note that sizeof is not a library function. sizeof is

a compile-time unary operator [...] that can be used to compute the size of any object
K&R

So sizeof doesn't know how big the array is, the compiler knows how big the array is, and by definition

when applied to an array, the result is the total number of bytes in the array.
K&R

user3386109
  • 34,287
  • 7
  • 49
  • 68
7

A pointer and an array are 2 different data types.

Array can hold elements of similar data type. The memory for array is contiguous.

Pointer is used to point to some valid memory location.

sizeof(type) gives you the number of bytes of the type you pass.

Now if you pass array then the compiler knows that this is an array and number of elements in it and it just multiplies that many elements with the respective data-type size value.

In this case:

5*4 = 20

Again the sizeof(int) or sizeof(pointer) is platform dependent. In this case you are seeing sizeof(pointer) as 8.

Gopi
  • 19,784
  • 4
  • 24
  • 36
4

No, arrays do not decay as operands of the sizeof operator. This is one of the few places where arrays don't decay. If an int is 4 bytes on your machine, then the total number of bytes of the array should be 20 (4 * 5). We don't even need an object to test this.

sizeof(int[5]) // 20
sizeof(int*)   // 8 on a 64-bit machine
2

C11: 6.5.3.4 (p2)

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. [...]

In the declaration

int array[5]  

the type of array is an array of 5 ints. The compiler will determine the size of array from this type.

haccks
  • 104,019
  • 25
  • 176
  • 264
0

Try this

int x = sizeof(array)/sizeof(int);
printf("the size of the array is %d\n", x);
lappet
  • 116
  • 1
  • 7