I am confused about the output of the following code.
#include
#include
using namespace std;
int main()
{
int a[] = {1,2,3};
First of all, realize that there is a difference between an object1 and the expression that we use to refer to that object. In your code, a
is an expression that refers to an object large enough to store 3 int
values.
Except when it is the operand of the sizeof
or unary &
operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T
" will be converted ("decay") to an expression of type "pointer to T
", and the value of the expression will be the address of the first element of the array.
Given a statement like
cout << a;
the expression a
has type "3-element array of int
"; since a
is not an operand of the sizeof
or unary &
operators, it will be converted to an expression of type "pointer to int
", and the value of the expression will be the address of the first element in the array.
OTOH, given a statement like
cout << &a;
the expression a
is the operand of the unary &
operator, so the rule doesn't apply; instead, the type of the expression is "pointer to 3-element array of int
", and the value of the expression is the address of the array.
In both C and C++, the address of the array and the address of the first element of the array are the same, so both expressions yield the same value, but the types of the two expressions are different (int *
vs. int (*)[3]
).
In the statement
cout << sizeof a; // or sizeof (a)
the expression a
is the operand of the sizeof
operator, so again, the conversion rule doesn't apply; instead, the expression sizeof a
evaluates to the number of bytes used by the array (in this case, 12).
In the statement
cout << sizeof &a; // or sizeof (&a)
the expression &a
evaluates to the address of the array and has type int (*)[3]
, so sizeof &a
evaluates to the number of bytes used by the pointer type (in your case, 4 bytes).
In both C and C++, when you declare an array like
int a[3];
the only storage set aside is for the 3 array elements; there's no separate storage for an a
variable that points to the first element of the array (which is why a
and &a
yield the same value).
In C, the expression a
is a primary expression which designates an array object. In a context where this expression is evaluated, it produces a value which is of pointer type, and points to the first element of the array.
This is a special evaluation rule for arrays. It does not mean that a
is a pointer. It isn't; a
is an array object.
When the sizeof
of &
operators are applied to a
, it is not evaluated. sizeof
produces the size of the array, and &
takes its address: it produces a pointer to the array as a whole.
The values of the expressions a
and &a
point to the same location, but have a different type: a pointer to type of the array element (such as pointer to int
), versus the type of the array (such pointer to array of 10 int) respectively.
C++ works very similarly in this area for compatibility with C.
There are other situations in C where the value of an expression which denotes a value or object of one type produces a value of another type. If c
has type char
, then the value of c
is a value of type int
. Yet &c
has type char *
, and sizeof c
produces 1. Just like an array is not a pointer, c
is not an int
; it just produces one.
C++ isn't compatible in this area; character expressions like names of char
variables or character constants like 'x'
have type char
. This allows void foo(int)
and void foo(char)
to be different overloads of a function foo
. foo(3)
will call the first one, and foo('x')
the second.
An array is not a pointer, but an array decays to a pointer when you try to use it like one. In your case printing the address of the array automatically converts it into a pointer.
There's little difference between the automatically converted pointer and the one created explicitly with &
, except that one is a pointer to a single element while the other is a pointer to the entire array. If you had used &a[0]
then they would be identical.