When you declare and define an array, the name of the array is an expression that evaluates to the address of the first element of the array. Think of the name as a constant that holds the address of the first element.
Once memory has been allocated for the array, the address of the array cannot be changed. Consequently, the value of the array identifier (name) cannot be changed either.
In your code, when you have
p = numbers++;
you are asking that numbers
, which has the constant value of the address of the first element of the array, be incremented and point to the second element instead. This is not a legal operation. The increment operand requires a modifiable lvalue
, and the name of the array is not a modifiable lvalue
.
What is an lvalue
? It is a locator value
: something that identifies an area of memory that can hold another value. So when you declare:
int a = 5;
a
signifies an area of memory large enough to hold an int
, and the int
held in that area of memory is 5
. You can change that int
by assignment:
a = 7;
but the identifier a
still signifies the same area of memory. This means a
is a modifiable lvalue
.
When you declare and define your array:
int numbers[] = { 1, 2, 3, 4, 5, 6 };
numbers
is an lvalue
, in that it specifies an area of memory that holds the array of specified integers, but it is not modifiable
. You can change the value of the elements in numbers
, but you cannot change the value of numbers
itself. numbers
always evaluates to &numbers[0]
.
If you want to change where p
points so that it points to the second element instead of the first, use:
p = numbers + 1;
This does not change the value of numbers
itself, only that of p
. numbers
is still &numbers[0]
and p
will be &numbers[1]
.
Hope this is clear!