Could someone explain this little code snippet for me?
Given:
int a[3] = {2,3,4};
Why does the following evaluate to true?
static_cast<void *>(a) == static_cast<void *>(&a); // Why is this true?
Is this saying that the address of a is the same as a? If so, why is this true?
It is because address of the variable a concides with the address of the first element of array a. You can also think of a is &a[0] which is clearer when we say "the address of the first element of the array").
Another example,
struct X
{
int i;
};
X x;
Here also the address of variable x concides with the address of x.i (which is the first element of the aggregate), so this would print 1:
std::cout << (&x == &(x.i)) << std::endl; //1
So in your case, &a is like &x, and a (or &a[0]) is like &(x.i).
Note that in C++ a and x are both called aggregate (see my answer here: What is an aggregate?)
In almost all contexts, the name of an array decays into a pointer to the first element of the array. So in static_cast<void*>(a), the a decays into &a[0]; it's type is "pointer to int". The expression evaluates to the address of the first element of the array. In static_cast<void*>(&a), however, &a is the address of the array itself; its type is "pointer to array of 3 int". That's why the casts are needed here: the two expressions without the casts would have different types, and could not be compared. Both can be converted to void* and compared. So what this code is illustrating is that the address of the first element of an array is the same as the address of the array, i.e., there's no padding at the front.
The name of an array usually evaluates to the address of the first element of the array, so array and &array have exact the same value.
However, they are different types. For the following array:
int a[8];
a+1 is the address of the array a + sizeof(int)
but &a+1 will be the address of the array a + 8 * sizeof(int).
Related
When p is a pointer to an array, why :
*p == p == &*p
Simple program, just a two dimension arrays in c++ :
int p[][3] = {{1,2,3}};
cout << p << " " << *p << " " << &*p;
result: 0x22fe20 0x22fe20 0x22fe20
The array p decays to a pointer to its first element when you print it. That's the same as &p. As for &*p that's the address of whatever the dereferenced p points to. Which is again the first element - same as the first two.
The type are different though. Even if the addresses are the same. p is an array, but &p is a pointer to int array.
When an array's value is used (p in this case), it implicitly converts to pointer to first element (same as &p[0]). Such conversion is called decaying.
Also, the first element of an array is at the same address where the array is.
p decays to &p[0]. It is the address of the first element of p which is the same address as the array p itself.
*p Here, the p first decays to &p[0], so the full expression is equivalent to *&p[0]. The *& cancel each other out (by definition in C; C++ uses different wording, but the effect is the same) As such, it is an lvalue to p[0] i.e. the first element of the array. In this case, that element is another array, and so its value decays to pointer to the first element (i.e. &p[0][0]). Since the address of the first element is the same as the address of the array, the address of p[0][0] is same as address of p[0] which is same as address of p.
&*p As before, &* cancel each other out and result is same as using just p.
In memory, a 4x4 2D array looks like this:
*
..0000111122223333..
XXXXXXXXXXXXXXXX
YYYY
Z
In this diagram, each column represents a memory location. Columns marked with X are where the 2D array is stored.
Each column marked with 0 is an element of the first subarray, and each one with 1 are elements of the second subarray and so forth.
Columns marked with Y are where the first subarray is stored.
Column marked with Z is the first element of the first subarray.
As you may notice, X, Y and Z all start on the same address marked with *. This is the address of the array, the address of the first subarray and the address of the first element of the first subarray.
p is a pointer to the beginning of the array.
*p is a pointer to the first array in that array (aka the beginning of the array)
&*p is the same thing as p, syntactically.
If you have an array declared for example like this
int a[] = { 1, 2, 3 };
then used in expressions (with rare exceptions as for example an operand of the operator sizeof) the array designator is implicitly converted to pointer to its first element. So in this statement
std::cout << a;
is the same as
std::cout << &a[0];
or the same as
std::cout << &*a;
In your example *p is an array {1,2,3} that represents the first element of the array p.
Used as an expression in the statement
std::cout << *p;
it is converted to the address of its first element that is it is the address of the first element equal to 1.
All these addresses point to the start of the extent allocated to the array. So though the types of for example the expression p and expression *p are different (the first expression has the type int ( * )[3] and the second expression has the type int *) nevertheless their values are equal.
This question already has answers here:
How come an array's address is equal to its value in C?
(6 answers)
Closed 7 years ago.
As a beginner programmer I am dealing with some simple problems related to Pointers. In the following code I found the value of *a and a are same in hexadecimal. But I can't understand the reason.
#include <stdio.h>
#include <stdlib.h>
main(){
int a[5][5];
a[0][0] = 1;
printf("*a=%p a=%p \n", *a, a);
return 0;
}
Here is the output:
*a=0x7ffddb8919f0 a=0x7ffddb8919f0
An array and its first element have the same address.:)
For this declaration
int a[5][5];
expression a used in the printf call is implicitly converted to the pointer to its first element. Expression *a yields the first element of the array that is in turn a one-dimensional array that also is converted to a pointer to its first element.
Thus expressions a and *a have the same value as expression &a[0][0]
In C and C++ languages values of array type T [N] are implicitly converted to values of pointer type T * in most contexts (with few exceptions). The resultant pointer points to the first element of the original array (index 0). This phenomenon is informally known as array type decay.
printf argument is one of those contexts when array type decay happens.
A 2D array of type int [5][5] is nothing else than an "1D array of 1D arrays", i.e. it is an array of 5 elements, with each element itself being an array of 5 ints.
The above array type decay rule naturally applies to this situation.
The expression a, which originally has array type int [5][5], decays to a pointer of type int (*)[5]. The pointer points to element a[0], which is the beginning of sub-array a[0] in memory. This is the first pointer you print.
The expression *a is a dereference operator applied to sub-expression a. Sub-expression a in this context behaves in exactly the same way as before: it decays to pointer of type int (*)[5] that points to a[0]. Thus the result of *a is a[0] itself. But a[0] is also an array. It is an array of int[5] type. It is also subject to array type decay. It decays to pointer of type int *, which points to the first element of a[0], i.e. to a[0][0]. This is the second pointer you print.
The reason both pointer values are the same numerically is that the beginning of sub-array a[0] corresponds to the same memory location as element a[0][0].
a can be considered a pointer to a pointer to an int (in reality, it's an array of array of int, but close enough).
So a and *a both point to the same address (which happens to be a[0][0]).
*a is still a pointer, and a[0] is the same address as a[0][0].
I am confused about the output of the following code.
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
int a[] = {1,2,3};
cout << a << " " << &a << endl;
cout << sizeof(a) << " " << sizeof(&a) << endl;
return 0;
}
The output is
0xbfcd3ae4 0xbfcd3ae4
12 4
How can a and &a print the same expression but have different sizes?
I always thought that for any array, its name always has the value = address of the first byte.
Also &a should not make sense, since one cannot have an address (obtained with the & operator) to an address(the value of a). Yet the code gives an output and infact 'a == &a'
according to the output.
Similarly why is the output of sizeof(a) = 12 (which is the total memory occupied)
by the array? a being a "pointer" itself sizeof(a) = 4 bytes (on my 32 bit Ubuntu 11.04)
Obviously there is some misconception I am having. Could some one sort this out for me ?
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.
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).
1. In the sense of something that occupies memory, not the sense of an instance of a class
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.
Look at this following code for better understanding:
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
int a[] = {1,2,3};
cout << a << " " << &a << endl;
cout << a+1 << " " << &a+1 << endl;
cout << sizeof(a) << " " << sizeof(&a) << endl;
return 0;
}
Output:
0x7fffb231ced0 0x7fffb231ced0
0x7fffb231ced4 0x7fffb231cedc
12 8
We got same address for a and &a. So we you may think they are same. But that not true, because a variable (a) and its address (&a) cannot be same.
Both printed address, but both are printing different addresses, "a” is a “pointer to the first element of array” but “&array” is a “pointer to whole array”.
That's why when we printed a+1 we got 0x7fffb231ced4which is address to second element in array (and since it array of integers, its increased by 4) while &a+1 got us 0x7fffb231cedc which is increment of 4*3= 12 (c means 12 in hex) because we had 3 elements in array. &arr+1 points to next memory location after array.
Also this fundamental difference is what results in different in sizes of a and &a. size of a is actually the size of array while size of &a is size of pointer.
I was asked to give the output of the following code in an interview.
int a[] = {1,2,3,4,5};
int *p = &a + 1;
printf("%d, %d", *(a+1), *(p - 1));
I said I could not determine the result of the second one, so I failed the interview.
When I got back to home, and tried to compile the code, g++ will report an error, but gcc will only give a warning. The result printed is '2,5'.
Anyone knows why the C and C++ compiler behave differently on this?
a is an array of integers, which converts to a pointer to the first element when needed. a+1 invokes that conversion, and gives a pointer to the second element.
&a is a pointer to the array itself, not to the first element of it, so &a + 1 points beyond the end of the array (to the point where the second array would be, if it were a 2-dimensional array).
The code then converts that pointer (of type int (*)[5]) to a pointer to an integer (type int*). C++ doesn't allow such a conversion without an explicit reinterpret_cast, while C is more lenient in the pointer conversions it allows.
Finally (assuming that p and p2 are supposed to be the same thing), p - 1 points to the last element of a.
Well, a is array of 5 ints, so &a is a pointer to array of 5 ints. in C++, you can't assign that address in a int* without cast it. gcc (in C language) gives only warning, but I think that is not valid C.
For the code:
&a+1 is the next array after a, meaning, the address of the 6th element in a, so p-1 is the address of the 5th element of a.
(I'm not sure if &a+1 is legal. it's the address of the element that is after the array, which is usually legal, but since &a is not an array, it may be illegal.)
int a[] = {1,2,3,4,5};
int *p = &a + 1;
This is invalid C code.
The expression &a + 1 is of type int (*)[5]. You cannot assign an expression of type int (*)[5] to an int *.
Except with the generic object pointer type void *, there is no implicit conversion between object pointers. A cast is required to initialize p with &a + 1 value.
Where does C says this declaration is invalid?
int *p = &a + 1;
in the constraints of the assignment operator:
(C99, 6.5.16.1p1) "both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right"
And an int and an array type are not compatible types (see 6.2.7p1 for more on type compatibility).
well also, it is an initialization not an assignment, but the same constraint applies:
(C99, 6.7.8p11) "The initializer for a scalar shall be a single expression, optionally enclosed in braces. The initial value of the object is that of the expression (after conversion); the same type constraints and conversions as for simple assignment apply, taking the type of the scalar to be the unqualified version of its declared type."
The C++ compiler gave an error because &a evaluates to int(*)[5], which is a pointer to 5 integers, and you're attempting to assign it to an int*.
If you did fix the type, this code would print the second item in the array, followed by the address of the array.
My guess is that C decays the array into a pointer, resulting in &a evaluating to int**, and allows that to be assigned to int*. However, I don't do much C, so someone else may know better.
I have been programming c/c++ for many years, but todays accidental discovery made me somewhat curious... Why does both outputs produce the same result in the code below? (arr is of course the address of arr[0], i.e. a pointer to arr[0]. I would have expected &arr to be the adress of that pointer, but it has the same value as arr)
int arr[3];
cout << arr << endl;
cout << &arr << endl;
Remark: This question was closed, but now it is opened again. (Thanks ?)
I know that &arr[0] and arr evaluates to the same number, but that is not my question! The question is why &arr and arr evaluates to the same number. If arr is a literal (not stored anyware), then the compiler should complain and say that arr is not an lvalue. If the address of the arr is stored somewhere then &arr should give me the address of that location. (but this is not the case)
if I write
const int* arr2 = arr;
then arr2[i]==arr[i] for any integer i, but &arr2 != arr.
#include <cassert>
struct foo {
int x;
int y;
};
int main() {
foo f;
void* a = &f.x;
void* b = &f;
assert(a == b);
}
For the same reason the two addresses a and b above are the same. The address of an object is the same as the address of its first member (Their types however, are different).
arr
_______^_______
/ \
| [0] [1] [2] |
--------------------+-----+-----+-----+--------------------------
some memory | | | | more memory
--------------------+-----+-----+-----+--------------------------
^
|
the pointers point here
As you can see in this diagram, the first element of the array is at the same address as the array itself.
They're not the same. They just are at the same memory location. For example, you can write arr+2 to get the address of arr[2], but not (&arr)+2 to do the same.
Also, sizeof arr and sizeof &arr are different.
The two have the same value but different types.
When it's used by itself (not the operand of & or sizeof), arr evaluates to a pointer to int holding the address of the first int in the array.
&arr evaluates to a pointer to array of three ints, holding the address of the array. Since the first int in the array has to be at the very beginning of the array, those addresses must be equal.
The difference between the two becomes apparent if you do some math on the results:
arr+1 will be equal to arr + sizeof(int).
((&arr) + 1) will be equal to arr + sizeof(arr) == arr + sizeof(int) * 3
Edit: As to how/why this happens, the answer is fairly simple: because the standard says so. In particular, it says (§6.3.2.1/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.
[note: this particular quote is from the C99 standard, but I believe there's equivalent language in all versions of both the C and C++ standards].
In the first case (arr by itself), arr is not being used as the operand of sizeof, unary &, etc., so it is converted (not promoted) to the type "pointer to type" (in this case, "pointer to int").
In the second case (&arr), the name obviously is being used as the operand of the unary & operator -- so that conversion does not take place.
The address is the same but both expressions are different. They just start at the same memory location. The types of both expressions are different.
The value of arr is of type int * and the value of &arr is of type int (*)[3].
& is the address operator and the address of an object is a pointer to that object. The pointer to an object of type int [3] is of type int (*)[3]
They are not the same.
A bit more strict explanation:
arr is an lvalue of type int [3]. An attempt to use
arr in some expressions like cout << arr will result in lvalue-to-rvalue conversion which, as there are no rvalues of array type, will convert it to an rvalue of type int * and with the value equal to &arr[0]. This is what you can display.
&arr is an rvalue of type int (*)[3], pointing to the array object itself. No magic here :-) This pointer points to the same address as &arr[0] because the array object and its first member start in the exact same place in the memory. That's why you have the same result when printing them.
An easy way to confirm that they are different is comparing *(arr) and *(&arr): the first is an lvalue of type int and the second is an lvalue of type int[3].
Pointers and arrays can often be treated identically, but there are differences. A pointer does have a memory location, so you can take the address of a pointer. But an array has nothing pointing to it, at runtime. So taking the address of an array is, to the compiler, syntactically defined to be the same as the address of the first element. Which makes sense, reading that sentence aloud.
I found Graham Perks' answer to be very insightful, I even went ahead and tested this in an online compiler:
int main()
{
int arr[3] = {1,2,3};
int *arrPointer = arr; // this is equivalent to: int *arrPointer = &arr;
printf("address of arr: %p\n", &arr);
printf("address of arrPointer: %p\n", &arrPointer);
printf("arr: %p\n", arr);
printf("arrPointer: %p\n", arrPointer);
printf("*arr: %d\n", *arr);
printf("*arrPointer: %d\n", *arrPointer);
return 0;
}
Outputs:
address of arr: 0x7ffed83efbac
address of arrPointer: 0x7ffed83efba0
arr: 0x7ffed83efbac
arrPointer: 0x7ffed83efbac
*arr: 1
*arrPointer: 1
It seems the confusion was that arr and arrPointer are equivalent. However, as Graham Parks detailed in his answer, they are not.
Visually, the memory looks something like this:
[Memory View]
[memory address: value stored]
arrPointer:
0x7ffed83efba0: 0x7ffed83efbac
arr:
0x7ffed83efbac: 1
0x7ffed83efbb0: 2
0x7ffed83efbb4: 3
As you can see, arrPointer is a label for memory address 0x7ffed83efba0 which has 4 bytes of allocated memory which hold the memory address of arr[0].
On the other hand, arr is a label for memory address 0x7ffed83efbac, and as per Jerry Coffin's answer, since the type of variable arr is "array of type", it gets converted to a "pointer of type" (which points to the array's starting address), and thus printing arr yields 0x7ffed83efbac.
The key difference is arrPointer is an actual pointer and has its own memory slot allocated to hold the value of the memory it's pointing to, so &arrPointer != arrPointer. Since arr is not technically a pointer but an array, the memory address we see when printing arr is not stored elsewhere, but rather determined by the conversion mentioned above. So, the values (not types) of &arrPointer and arrPointer are equal.