1

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.

5
  • 4
    Duplicate, many times over. In a function argument list, the array is converted to int *. Commented Feb 2, 2021 at 0: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? Commented Feb 2, 2021 at 0: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. Commented Feb 2, 2021 at 0: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. Commented Feb 2, 2021 at 0:46
  • 1
    See 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). There are others, mostly not as widely approved of and many a duplicate of these. There are some questions dual tagged with both c and c++; I've not linked to those. Commented Feb 2, 2021 at 0:58

1 Answer 1

5

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.

Sign up to request clarification or add additional context in comments.

8 Comments

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: 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.
@DavidSchwartz: What? No, that is not a reason it is not possible.
@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)[].
@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.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.