C++11 code:
int a[3];
auto b = a; // b is of type int*
auto c = &a; // c is of type int(*)[1]
C code:
int a[
The sizeof
operator should behave differently, for one, especially if you change the declaration of a
to a different number of integers, such as int a[7]
:
int main()
{
int a[7];
auto b = a;
auto c = &a;
std::cout << sizeof(*b) << std::endl; // outputs sizeof(int)
std::cout << sizeof(*c) << std::endl; // outputs sizeof(int[7])
return 0;
}
For me, this prints:
4
28
That's because the two pointers are very different types. One is a pointer to integer, and the other is a pointer to an array of 7 integers.
The second one really does have pointer-to-array type. If you dereference it, sure, it'll decay to a pointer in most cases, but it's not actually a pointer to pointer to int. The first one is pointer-to-int because the decay happened at the assignment.
Other places it would show up is if you really did have two variables of pointer-to-array type, and tried to assign one to the other:
int main()
{
int a[7];
int b[9];
auto aa = &a;
auto bb = &b;
aa = bb;
return 0;
}
This earns me the error message:
xx.cpp: In function ‘int main()’:
xx.cpp:14:8: error: cannot convert ‘int (*)[9]’ to ‘int (*)[7]’ in assignment
aa = bb;
This example, however, works, because dereferencing bb
allows it to decay to pointer-to-int:
int main()
{
int a;
int b[9];
auto aa = &a;
auto bb = &b;
aa = *bb;
return 0;
}
Note that the decay doesn't happen on the left side of an assignment. This doesn't work:
int main()
{
int a[7];
int b[9];
auto aa = &a;
auto bb = &b;
*aa = *bb;
return 0;
}
It earns you this:
xx2.cpp: In function ‘int main()’:
xx2.cpp:14:9: error: incompatible types in assignment of ‘int [9]’ to ‘int [7]’
*aa = *bb;
The identity of any object in C++ is determined by the pair of its type and its address.
There are two distinct objects with the same address in your example: The array itself, and the first element of the array. The first has type int[1]
, the second has type int
. Two distinct objects can have the same address if one is a subobject of the other, as is the case for array elements, class members, and class base subobjects.
Your example would be clearer if you wrote:
int a[5];
int (*ptr_to_array)[5] = &a;
int * ptr_to_array_element = &a[0];
But you have taken advantage of the fact that the id-expression a
for the array decays to a pointer to the array's first element, so a
has the same value as &a[0]
in your context.
Consider this example:
#include<stdio.h>
int main()
{
int myArray[10][10][10][10]; //A 4 Dimentional array;
//THESE WILL ALL PRINT THE SAME VALUE
printf("%d, %d, %d, %d, %d\n",
myArray,
myArray[0],
myArray[0][0],
myArray[0][0][0],
&myArray[0][0][0][0]
);
//NOW SEE WHAT VALUES YOU GET AFTER ADDING 1 TO EACH OF THESE POINTERS
printf("%d, %d, %d, %d, %d\n",
myArray+1,
myArray[0]+1,
myArray[0][0]+1,
myArray[0][0][0]+1,
&myArray[0][0][0][0]+1
);
}
You will find that all the 5 values printed in first case are all equal. Because they point to the same initial location.
But just when you increment them by 1 you see that different pointers now jump (point) to different locations. This is because myArray[0][0][0] + 1
will jump by 10 integer values that is 40 bytes, while myArray[0][0] + 1
will jump by 100 integer values i.e by 400 bytes. Similarly myArray[0] + 1
jumps by 1000 integer values or 4000 bytes.
So the values depend on what level of pointer you are referring to.
But now, if I use pointers to refer all of them:
#include<stdio.h>
int main()
{
int myArray[10][10][10][10]; //A 4 Dimentional array;
int * ptr1 = myArray[10][10][10];
int ** ptr2 = myArray[10][10];
int *** ptr3 = myArray[10];
int **** ptr4 = myArray;
//THESE WILL ALL PRINT THE SAME VALUE
printf("%u, %u, %u, %u\n", ptr1, ptr2, ptr3, ptr4);
//THESE ALSO PRINT SAME VALUES!!
printf("%d, %d, %d, %d\n",ptr1+1,ptr2+1,ptr3+1,ptr4+1);
}
So you see, different levels of pointer variables do not behave the way the array variable does.