0

I can get the sizeof an object in an array in a local function:

int xa[] = {3,5};
printf("Sizeof: %zu\n", sizeof(xa));

Sizeof: 8

But if I pass it to a function, I get a warning:

void sum_array(int x[]) {
    int sum=0;
    for (int i=0; i < (sizeof(x) / sizeof(*x)); i++ ) {
        sum += x[i];
    }
    printf("%d\n", sum);
}

'sizeof' on array function parameter ‘x’ will return size of ‘int *’ [-Wsizeof-array-argument]

What's the reason that this occurs? I can suppress this by changing the formal parameter from int x[] to int* x, but I'd like to understand why this is occurring. My thought that was within a function parameter that type* x and type x[] were identical, but I guess I was mistaken.

David542
  • 104,438
  • 178
  • 489
  • 842
  • 4
    Duplicate, many times over. In a function argument list, the array is converted to `int *`. – Jonathan Leffler Feb 02 '21 at 00:37
  • @JonathanLeffler so would it be accurate to say when `int x[]` is passed to a function it goes to `func(&x[0])` ? Is there any way to keep the size information then (such as to do `sizeof` or do you have to explicitly pass it another argument, such as `int size` to convey the original array dimensions? – David542 Feb 02 '21 at 00:41
  • @JonathanLeffler: This is not a duplicate of that because this question does not ask about why `sizeof` produces a value OP did not expect but rather asks about the warning and the difference in compiler behavior between declaring the parameter as an array versus declaring it as a pointer. – Eric Postpischil Feb 02 '21 at 00:44
  • Yes, it would be accurate enough to say that `func(x)` and `func(&x[0])` are equivalent. The size information is irrevocably lost when the array is passed to a function. See C11 [§6.7.6.3 Function declarators (including prototypes) ¶7](http://port70.net/~nsz/c/c11/n1570.html#6.7.6.3p7). – Jonathan Leffler Feb 02 '21 at 00:46
  • 1
    See [How do I determine the size of my array in C?](https://stackoverflow.com/questions/37538/how-do-i-determine-the-size-of-my-array-in-c), especially the second most voted answer. See also [Passing array to function changes function `sizeof(array)`](https://stackoverflow.com/questions/52975032/passing-array-to-function-changes-function-sizeofarray). There are others, mostly not as widely approved of and many a duplicate of these. There are some questions dual tagged with both [tag:c] and [tag:c++]; I've not linked to those. – Jonathan Leffler Feb 02 '21 at 00:58

1 Answers1

3

The warning occurs because the declaration int x[] suggests you are thinking of the parameter as an array, but it is not and so may have effects you did not intend.

Array parameters are automatically adjusted to be pointers.

When you declare the parameter as int *x, which is the same as the array parameter after it is adjusted, the compiler knows you are thinking of the parameter as a pointer, so it expects you know that sizeof x will produce the size of the pointer, not the array. So it does not warn you. However, the result of sizeof will be the same either way, and it will not tell you the size of the array.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • That's helpful thank you -- (from my comment above) -- would it be accurate to say that when int x[] is passed to a function it goes to func(&x[0]) ? Is there any way to keep the size information then (such as to do sizeof or do you have to explicitly pass it another argument, such as int size to convey the original array dimensions? – David542 Feb 02 '21 at 00:43
  • 1
    @David542: Yes, an array passed to a function is automatically converted to a pointer to its first element. (This is true of an array used in any expression except as the operand of `sizeof` or unary `&` or, for a string literal, used to initialize an array.) To know the size in the function, you must pass that information to the function or otherwise make it available to the function. – Eric Postpischil Feb 02 '21 at 00:46
  • @DavidSchwartz: What? No, that is not a reason it is not possible. – Eric Postpischil Feb 02 '21 at 00:46
  • @DavidSchwartz: So what? First, `sizeof` does not have to be evaluated at compile time, and it generally cannot be for variable-length arrays. Second, `char a[sizeof(b)];` could declare a variable-length array, and must if `b` has variable length. Or the specification of `sizeof` in C 2018 6.5.3.4 would say the result is an integer constant only if the size of its operand were visible. E.g., you currently cannot apply `sizeof` to objects of incomplete type. That does not prevent us from declaring things with incomplete types. E.g., you cannot apply `sizeof` to `*y` for parameter `int (*y)[]`. – Eric Postpischil Feb 02 '21 at 00:52
  • @EricPostpischil one of the most common duplicates – 0___________ Feb 02 '21 at 01:36
  • @0___________: As I commented on the question, it is not a duplicate because it asks a different question: Why the compiler warns with one declaration but not another. The fact that the question **involves** an issue that is addressed elsewhere does not make it a duplicate. – Eric Postpischil Feb 02 '21 at 01:40
  • @EricPostpischil It is exactly the dupe. Why size of the array as a parameter cannot be determined using sizeof, thus warning – 0___________ Feb 02 '21 at 01:45
  • 1
    @0___________: It is not the same question; “Why does `sizeof` not produce the array size?” is not the same question as “Why does the compiler warn when the parameter is declared `int x[]` but not when it is declared `int *x`?”. Answering the former question does not answer the latter question; it does not explain why the compiler behaves differently for the two parameter declarations even though `sizeof` behaves the same for them. – Eric Postpischil Feb 02 '21 at 02:55