-2
void Size(int A[], int size){
    printf("Size of A = %d\nSize of A[0] = %d\n\n", sizeof(A), sizeof(A[0]));
}

when doing so I get an unexpected answer:

Size of A = 8
Size of A[0] = 4

As I know while we pass array to a function we use "pass by reference" and by checking sizeof(A) we should get the size of array type. May you help me solve this problem please?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Gendozz
  • 83
  • 5
  • 2
    there's no `pass by reference` in C. The only type in C is pass by value. C and C++ are very different languages – phuclv Aug 01 '21 at 08:21
  • `A` is an array (i.e. a memory address), which is 8 bytes on a 64 bit machine. `A[0]` is an int, so 32 bits/4 bytes. The compiler literally can't give you the standard response for that you're expecting when you do `sizeof(array)` because it's unsized (`int[]` vs int[size]`) – Tibrogargan Aug 01 '21 at 08:21
  • 1
    @Tibrogargan `A` is a pointer, not an array. – interjay Aug 01 '21 at 08:27
  • @interjay pretty sure C treats `int[]` differently to `int *`. While pointers and unsigned arrays are effectively the same, the compiler can do things with an unsized array it can't do with a pointer – Tibrogargan Aug 01 '21 at 08:31
  • no, it's just syntactic sugar – Elazar Aug 01 '21 at 08:32
  • 1
    @Tibrogargan You're wrong, `int[]` and `int*` are the same thing as function parameters. Even `int A[10]` would be a pointer. See the answers to this question. – interjay Aug 01 '21 at 08:32
  • 4
    You're comparing the sizes of `A` and `A[0]`, which in general may be different, rather than the sizes of `*A` and `A[0]`, as the subject claims, which should be the same. Also, you need to use `%zu` to print `sizeof` values. Using `%d` invokes undefined behavior. – Tom Karzes Aug 01 '21 at 08:32
  • Yup, I stand corrected. Was under the impression that the syntactic sugar also carried some semantic value. No idea where I got that. – Tibrogargan Aug 01 '21 at 08:43

4 Answers4

0

Because you can't pass arrays as arguments to functions (they decay into pointers), the compiler will silently change the declaration of an array argument into a pointer. So the argument int A[] is not actually an array -- it is really a pointer. So you're printing the size of a pointer.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
0

When you pass an array as an argument of a function it decays to a pointer to the first element of that array, int A[] becomes int *A, in fact you can use one or the other in the function declaration, it's the same.

sizeof A is the size in bytes of that pointer, it's as if you use sizeof(int*), whereas sizeof A[0] is the size in bytes of the first element of the array, which is an int, it's as if you use sizeof(int).

Note that pass by reference is not a feature of the language, perhaps you're thinking of C++, what you are doing is passing the pointer by value (i.e. passing the memory address stored in the pointer) which is often referred to by pass by pointer.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
0

In C passing by reference means passing an object indirectly through a pointer to it. Thus dereferencing the pointer you will get a direct access to the object.

When an array designator is passed to a function it is implicitly converted to a pointer to its first element. From the C Standard (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.

On the other hand, a parameter having an array type is adjusted by the compiler to pointer to the element type of the array. From the C Standard (6.7.6.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.

So this function declaration

void Size(int A[], int size);

is equivalent to

void Size(int *A, int size);

As a result all elements of the array in fact passed by reference through the pointer to the first element of the array. Using the pointer arithmetic you can get a direct access to any element of the array.

Pay attention to that the type of an expression with the sizeof operator is size_t. So you have to use the conversion specifier %zu instead of %d in the call of printf.

printf("Size of A = %zu\nSize of A[0] = %zu\n\n", sizeof(A), sizeof(A[0]));

In this call sizeof( A ) yields the size of the pointer A due to the implicit conversion of the passed array to pointer to its first element and due to adjusting the function parameter to pointer to the array element type by the compiler.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

This warning (without -Wall) should have made the result less unexpected:

 warning: 'sizeof' on array function parameter 'A' will return size of 'int *' [-Wsizeof-array-argument]

Pass by reference means you do not pass the array itself, but only a reference to it, i.e. an address aka pointer. That pointer only knows what it points to (int), so sizeof *A is like sizeof A[0].

Even as VLA:

void Size(int size, int A[size]) 

sizeof gives the same warning.

But why should there be an exception to the decay of array arguments in this case, when the size variable holds all the information?