4

why does this code work?

#include <stdio.h>

void func(int v[]){
    v[0] = 1;
}

int main(){
    int v[5] = {0};
    func(v);
    for (int i = 0; i < 5; i++)
    {
        printf("%d ", v[i]);
    }
}

The output I get from this is '1 0 0 0 0' but why? I'm not passing a pointer, why can the function change the array in my main?

4
  • 3
    You cannot pass an array to a function except as part of a struct. Here the array decays to a pointer, and the function writes to the first element of the caller's array. Even when you define the argument as int v[] it is still not passed an array. Commented Dec 29, 2021 at 20:04
  • 2
    int v[] is virtually synonymous to int *v. Commented Dec 29, 2021 at 20:08
  • @ikegami: That particular one might be, but array declarations in function parameter declarations are not always synonymous with pointer declarations. There are at least two differences. One is that the array declaration int (x[])[] is not allowed but the pointer declaration int (*x)[] is, because arrays must have complete element types but pointers can point to incomplete types. Another is that an array declaration can contain an expression in the brackets that will be evaluated, and a pointer declaration has no place for this. Commented Dec 29, 2021 at 20:19
  • @ikegami: int (*x)[] is not an array declaration. It declares a pointer, and it is not compatible with int **x. The former is a pointer to an array, and the latter is a pointer to a pointer. E.g, the code void bar(int (*x)[]); void bar(int **x); will yield a diagnostic from the compiler that the types conflict. Commented Dec 29, 2021 at 21:01

3 Answers 3

7

Yes, you are passing a pointer.

When you write void func(int v[]) to declare your function signature, it is equivalent to writing void func(int * v).

When you write func(v) to call your function, it is equivalent to func(&v[0]).

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

4 Comments

Since array arguments behave this way, I personally prefer to just avoid putting arrays in function signatures and I use explicit pointers instead.
Re "I personally prefer to just avoid putting arrays in function signatures", One could use * to indicate a single value and [] to indicate a pointer to an array.
@DavidGrayson: If you only use pointers in function declarations, you miss the fun of #include <stdio.h> / int main(int argc, char *argv[puts("Hello, world.")]) {}.
@DavidGrayson, from C99 it is possible to write void foo(int v[static 1]). It will tell the compiler that at least one entry pointed by a pointer v is valid. Moreover it makes the declaration of parameter visually different from the declaration of an array.
4

This function declaration

void func(int v[]){
    v[0] = 1;
}

is adjusted by the compiler to the declaration

void func(int *v){
    v[0] = 1;
}

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

On the other hand, in this call

func(v);

the array designator v is implicitly converted to a pointer to its first element.

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.

That is the function call is equivalent to

func( &v[0] );

So in fact the first element of the array is passed to the function by reference through a pointer to it. Dereferencing the pointer by means of the subscript operator (the expression v[0] is equivalent to the expression *v)

v[0] = 1;

the referenced first element of the array is changed.

Comments

0

It is because array is internally considered as a pointer. It's an identifier for a variable of type array, which has an implicit conversion to pointer of element type.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.