bhuwansahni
bhuwansahni

Reputation: 1844

Is an array argument passed to a function not a constant pointer?

Consider the code:

void foo(char a[]){
   a++;            //  works fine, gets compiled
   //... 
}

Now, consider this:

void foo(){
   char a[50];
   a++;            //  Compiler error
   //... 
}

I heard an array is equivalent to a constant pointer and can't be incremented as it is not a lvalue...

Then why does first code gets compiled, is it so because array arguments to functions are passed as a pointer, i.e. T[] is converted to T* for passing.. So, foo(a) passes a as a pointer.

But is it not back converted to T[] again because is declared as:

void foo(char a[]);

Upvotes: 8

Views: 1682

Answers (6)

Cosyn
Cosyn

Reputation: 5007

In C++, any function parameter of type "array of T" is adjusted to be "pointer to T". Try this code:

void foo(char a[]) {}  
void foo(char* a) {}  //error: redefinition  

They are indeed the same function.

So, why can we pass an array argument to a function as a pointer parameter? Not because an array is equivalent to a constant pointer, but because an array type can be implicitly converted to an rvalue of pointer type. Also note the result of the conversion is an rvalue, that's why you can't apply the operator ++ to an array, you can only apply this operator to an lvalue.

Upvotes: 3

wyq10
wyq10

Reputation: 226

When you pass an array a[] to a function, it passes the value of 'a', an address, into the function. so you can use it as a pointer in the function. If you declare an array in the function, 'a' is constant because you can't change its address in memory.

Upvotes: 1

Alok Save
Alok Save

Reputation: 206546

When you pass an array as an argument to a function, it decays to a pointer.
So the thing you increment inside the function body is a pointer, not an array.

Upvotes: 13

John Bode
John Bode

Reputation: 123488

I heard an array is equivalent to a constant pointer and can't be incremented as it is not a lvalue...

Almost.

An array expression is a non-modifiable lvalue; it may not be an operand to operators such as ++ or --, and it may not be the target of an assignment expression. This is not the same thing as a constant pointer (that is, a pointer declared as T * const).

An array expression will be replaced with a pointer expression whose value is the address of the first element of the array except when the array expression is an operand of the sizeof or unary & operators, or when the array expression is a string literal being used to initialize another array in a declaration.

When you call a function with an array argument, such as

int a[N];
...
foo(a);

the expression a is converted from type "N-element array of int" to "pointer to int" and this pointer value is what gets passed to foo; thus, the corresponding function prototype should be

void foo (int *arr) {...}

Note that in the context of a function parameter declaration, T a[] and T a[N] are identical to T *a; in all three cases, a is declared as a pointer to T. Within the function foo, the parameter arr is a pointer expression, which is a modifiable lvalue, and as such it may be assigned to and may be the operand of the ++ and -- operators.

Remember that all these conversions are on the array expression; that is, the array identifier or other expression that refers to the array object in memory. The array object (the chunk of memory holding the array values) is not converted.

Upvotes: 1

Potatoswatter
Potatoswatter

Reputation: 137830

This is a rather unfortunate feature inherited from the C language, with the rather yucky name of "decay." Since C once did not allow passing compound types by value, they decided to allow programmers to specify arrays as function parameter types, but only cosmetically. The array type decays to a pointer type, implementing a sort of pass-by-reference semantic different from the rest of the language. Ugly.

To recap (and others have already said this), the signature

void foo(char a[]); // asking for trouble

is unceremoniously mangled into

void foo(char *a);

… all for the sake of compatibility with ancient C code. Since you aren't writing ancient C code, you should not make use of this "feature."

However, you can cleanly pass a reference to an array. C++ requires that the size of the array be known:

void foo( char (&a)[ 50 ] );

Now a cannot be modified within the function (edit: its contents can, of course — you know what I mean), and only arrays of the right size may be passed. For everything else, pass a pointer or a higher-level type.

Upvotes: 11

Luchian Grigore
Luchian Grigore

Reputation: 258618

I heard an array is equivalent to a constant pointer

You can think of it that way, but they're not equivalent.

An array decays to a pointer when passed to a function, that's why inside the function it's valid.

Just because the signature is void foo(char a[]) doesn't make a an array.

Outside the function, it's just an array, and you can't do pointer arithmetics on it.

Upvotes: 4

Related Questions