athspk
athspk

Reputation: 6762

Miscalculation of array size inside a function

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

Answers (3)

John Bode
John Bode

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 the sizeof 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 keyword static 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

Argote
Argote

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

David Heffernan
David Heffernan

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

Related Questions