views:

948

answers:

10

why isn't the size of an array sent as a parameter the same as within main?

#include <stdio.h>

void PrintSize(int p_someArray[10]);

int main () {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* as expected 40 */
    PrintSize(myArray);/* prints 4 not 40 */
}

void PrintSize(int p_someArray[10]){
    printf("%d\n", sizeof(p_someArray));
}
+24  A: 

No, array-type is implicitly converted into pointer type when you pass it in to a function.

So,

void PrintSize(int p_someArray[10]){
printf("%zu\n", sizeof(p_someArray));
}

and

void PrintSize(int *p_someArray){
printf("%zu\n", sizeof(p_someArray));
}

are equivalent. So what you get is the value of sizeof(int*)

Prasoon Saurav
Ok but is there a way to print the size within the function?
Chris_45
In C++ you can pass the array by reference to the function but you cannot do that in C.
Prasoon Saurav
Allright, great thanks! And BTW that reference stuff, I remember that one shouldn't use that word in C as it has a special meaning in C++, I guess it is the stuff you are mentioning?
Chris_45
You'd need to pass the size of the array as a separate parameter. Then the size of the array would be sizeof(*p_someArray) * length
Aric TenEyck
Minor nit: `sizeof` operator returns an object of type `size_t`, so you should print it with `%zu` (C99), or cast it to `int` if you use `%d` like above in your `printf` calls.
Alok
@Chris_45: Yes I was referring to references(aliases) in C++
Prasoon Saurav
Alok's statement is correct. Using incorrect format specifier in printf(..) is UB.
Prasoon Saurav
@Chris_45: C has no references, but in C you can pass an array by pointer to the entire array as in: `void PrintSize(int (*p_someArray)[10])`. The inside the function you can access the array by using dereference operator `*`: `sizeof(*p_someArray)`. This will have the same effect as using references in C++.
AndreyT
+1  A: 

Arrays are only loosely sized. For the most part, an array is a pointer to memory. The size in your declaration only tells the compiler how much memory to allocate for the array - it's not associated with the type, so sizeof() has nothing to go on.

plinth
+3  A: 

Because arrays decay into pointers when they are passed as parameters. This is how C works, although you can pass "arrays" in C++ by reference and overcome this issue. Note that you can pass arrays of different sizes to this function:

 // 10 is superfluous here! You can pass an array of different size!
void PrintSize(int p_someArray[10]);
AraK
+2  A: 

In the C language, there is no method to determine the size of an unknown array, so the quantity needs to be passed as well as a pointer to the first element.

0A0D
In general, you should always pass the size (number of elements) of an array along with an array to a function, unless you have some other means of determining its size (e.g., a null character terminator at the end of `char[]` string arrays).
Loadmaster
A: 

The behavior is by design.

Same syntax in function parameter declaration means completely different thing than in local variable definition.

The reason is described in other answers.

Pavel Radzivilovsky
+1  A: 

You can't pass arrays to functions.

If you really wanted to print the size, you could pass a pointer to an array, but it won't be generic at all as you need to define the array size for the function as well.

#include <stdio.h>

void PrintSize(int (*p_anArray)[10]);

int main(void) {
    int myArray[10];
    printf("%d\n", sizeof(myArray)); /* as expected 40 */
    PrintSize(&myArray);/* prints 40 */
}

void PrintSize(int (*p_anArray)[10]){
    printf("%d\n", (int) sizeof(*p_anArray));
}
MR
+1  A: 

As others have stated, arrays decay to pointers to their first element when used as function parameters. It's also worth noting that sizeof does not evaluate the expression and does not require parentheses when used with an expression, so your parameter isn't actually being used at all, so you may as well write the sizeof with the type rather than the value.

#include <stdio.h>

void PrintSize1 ( int someArray[][10] );
void PrintSize2 ( int someArray[10] );

int main ()
{
    int myArray[10];
    printf ( "%d\n", sizeof myArray ); /* as expected 40 */
    printf ( "%d\n", sizeof ( int[10] ) ); /* requires parens */
    PrintSize1 ( 0 ); /* prints 40, does not evaluate 0[0] */
    PrintSize2 ( 0 ); /* prints 40, someArray unused */
}

void PrintSize1 ( int someArray[][10] )
{
    printf ( "%d\n", sizeof someArray[0] );
}

void PrintSize2 ( int someArray[10] )
{
    printf ( "%d\n", sizeof ( int[10] ) );
}
Pete Kirkham
+7  A: 

It's a pointer, that's why it's a common implementation to pass the size of the array as a second parameter to the function

+1  A: 

So, you will need to pass the lenght of the array as a second parameter. When you are writing code, in which you both declare an array of constant size, and later pass that array to a function, it is a pain to have the array-length constant show up several places in your code...

K&R to the rescue:

#define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0])) 

So now you can do e.g:

int a[10];
...
myfunction(a, N_ELEMENTS(a));
S.C. Madsen
A: 

In c++ you can pass an array by reference for this very purpose :

void foo(int (&array)[10])
{
    std::cout << sizeof(array) << "\n";
}
Alexandre C.