0

Can sizeof safely be used on an array that has been declared without an explicit size specified inside the square brackets, but which gets initialised in the declaration?

Consider the following code:

unsigned int arr[] = { 1, 2, 3 };
size_t bytes = sizeof arr;

If compiled on macOS with clang-800.0.42.1 without any special compiler flags, this yields the expected result of 12.
But does the C standard (or any C standard, if they differ on this) guarantee this to be the case? Or do I have to declare it like unsigned int arr[3] in order for it to be "sane"?

Siguza
  • 21,155
  • 6
  • 52
  • 89
  • 2
    Yes. The compiler knows the size. – Jonathan Leffler Jan 06 '17 at 18:16
  • I would also like to know if `sizeof( arr )` would work when it would be inside a function where the function header is something like `void somefunction ( int arr[], int n );` because from a calling routine you could pass any pointer of type `*int` in to `somefunction`. – ron Jan 06 '17 at 18:17
  • 1
    @ron - no, it would not, because what `somefunction` receives is a pointer, not an array. Within the function, `sizeof arr` would give you the same result as `sizeof (int *)`. – John Bode Jan 06 '17 at 18:17
  • No, When passed to a function, the size is only the size of a pointer. Not the size of the array – Gerhardh Jan 06 '17 at 18:18
  • @ron I don't think so, I believe `int arr[]` is just a nicer way of writing `int *arr` so you'll get the size of the pointer – torkleyy Jan 06 '17 at 18:19
  • 3
    @User9182736455 You are very wrong. Arrays are not pointers. – Eugene Sh. Jan 06 '17 at 18:19
  • @ron no, it does not work on an array which is a function argument, it gives the size of the pointer to which the array passed decays. – Weather Vane Jan 06 '17 at 18:21
  • @EugeneSh. I know but when passing an array to a function you instead pass the address of the first element; thus it contains no information about the length. You probably missed that I was talking about **passing arrays to functions** – torkleyy Jan 06 '17 at 18:21
  • @User9182736455 That's correct. But you still can't use `arr[]` an lvalue, for example. – Eugene Sh. Jan 06 '17 at 18:22
  • BTW, [an interesting and a non-obvious related topic](http://stackoverflow.com/questions/1810083/c-pointers-pointing-to-an-array-of-fixed-size) – Eugene Sh. Jan 06 '17 at 18:25
  • @EugeneSh. I think @User9182736455 was trying to say `int arr[]` and `int *arr` are the same in **function signature declaration** only – raymai97 Jan 07 '17 at 01:01
  • @ysap Would you mind justifying the edit you made? – Siguza Nov 01 '17 at 14:56
  • Mmm... C notation? If this was intentional (sorry, I miss how), then I can revert the change. – ysap Nov 01 '17 at 18:23
  • @ysap Well, I just like to not write parentheses unless they're required. In this case, they're not. – Siguza Nov 01 '17 at 18:31
  • In case you care - https://en.wiktionary.org/wiki/initialize – ysap Nov 01 '17 at 19:16
  • 1
    @ysap https://meta.stackoverflow.com/a/252504 – Siguza Nov 01 '17 at 20:08

2 Answers2

8

Yes, the standard guarantees that the array element count will be equal to the number of elements in the array initializer in case no size is specified. See C11 standard draft 6.7.9p22 and 6.7.9p25:

If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer. The array type is completed at the end of its initializer list.

EXAMPLE 2 The declaration

int x[] = { 1, 3, 5 };

defines and initializes x as a one-dimensional array object that has three elements, as no size was specified and there are three initializers.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Eugene Sh.
  • 17,802
  • 8
  • 40
  • 61
1

unsigned int arr[] = { 1, 2, 3 }; actually defines a complete array. The size of the array is known in this compilation unit and is n*sizeof(type) where n is the number of elements in the initialization list (here 3) and type is the underlying object type (here unsigned int).

That means that sizeof(arr) is defined in same scope as arr and has the expected value.


What would be completely different would be extern int arr[];. That would be a simple declaration that an array of that name will be provided in another compilation unit, but the compiler has no way to know its size. In that case using sizeof(arr) will be an error.

Another example of mere declaration is

void func(int arr[]) {
    ...
}

Here again the compiler only knows that the function will receive an int array, but again cannot know its size. But here the compiler generates a pointer that will receive the address of the array and sizeof(arr) is defined but is the size of that pointer and not the size of the original array.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • No, in your third example the compiler *doesn't* know that the function will receive an array. `void func(int arr[])` is exactly equivalent to `void func(int *arr)`; the declaration is "adjusted" at compile time. It's perfectly legal, for example, to call `func(NULL)`, or `func(&n)` where `n` is an `int` object that's not an array element. – Keith Thompson Jan 06 '17 at 19:41