Reputation: 6762
The following C program:
int doStuff(int afm[]);
int main(){
int afm1[9] = {1,2,3,4,5,6,7,8,9}; //size=9
int afmLength = sizeof(afm1)/sizeof(int);
printf("main: Length Of Array=%d\n", afmLength); //9 OK
int k = doStuff(afm1);
system("PAUSE");
return 0;
}
int doStuff(int afm[]){
int afmLength = sizeof(afm)/sizeof(int);
printf("doStuff: Length Of Array=%d\n", afmLength); //1 WRONG
return 1;
}
produces the following output:
main: Length Of Array=9
doStuff: Length Of Array=1
Why is the array size calculated correctly in main, but is wrong inside the function?
Upvotes: 0
Views: 489
Reputation: 123448
From the C language standard (draft n1256):
6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of thesizeof
operator or the unary&
operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
Memorize that paragraph, since one of the biggest sources of heartburn in C programming is how C treats array expressions.
When you call doStuff(afm1);
, the expression afm1
is implicitly converted from type "9-element array of int
" to "pointer to int
", and the expression's value is the same as &afm1[0]
. So what doStuff
receives is a pointer value, not an array.
In the context of a function parameter declaration, T a[]
and T a[N]
are both interpreted as T *a
:
6.7.5.3 Function declarators (including prototypes)
...
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the[
and]
of the array type derivation. If the keywordstatic
also appears within the[
and]
of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.
Since doStuff
receives a pointer value and not an array, the sizeof
trick doesn't work. In general, you have to explicitly tell a function how large of an array you're passing to it; you can't determine that from the pointer value itself.
So, when you call doStuff
from main
, you'll need to do something like
doStuff(afm1, sizeof afm1/sizeof *afm1);
...
int doStuff(int *afm, size_t afmsize)
{
...
}
Upvotes: 0
Reputation: 2155
Adding to David Heffernan's answer (which is correct), you should have another parameter which would be the array length passed onto your doStuff
method.
Upvotes: 2
Reputation: 612884
Because in main
you have an array and in the function you have a pointer to that array.
int doStuff(int afm[])
is equivalent to
int doStuff(int *afm)
Upvotes: 7