I’m studying about pointers. It’s quite confusing—maybe because I’m new. I have a question that what *(&a) indicates in the following short program.
On line 7, I know *(&a) means “value at address of variable a,” but on line 13, what does *(&a)=5 mean? When I assign &a=5, the compiler gives an error along the lines of “lvalue required as left operand of assignment,” but when I assign the value in *(&a), then it compiles with no error.
#include <stdio.h>
int main()
{
int *p, a = 2, b;
b = *(&a); // line 7
printf("%d", b);
p = &a;
printf("%d", p);
*(&a) = 5; // line 13
printf("%d", a);
return 0;
}
Given an int a; then &a gives you the address of a which is an int *. Given an int *p; the expression *p gives you the int that p is pointing to. So *(&a) is the value behind the address of a which is a. In other words *(&a) does the same as just a.
There are times when this is sort of useful. Given a std::vector<int>::iterator it; you can get a pointer to the int the iterator points to by dereferencing the iterator to get the int and then take the address, so you get &(*it).
This is covered in § 5.3.1 [expr.unary.op]:
1 The unary * operator performs indirection: the expression to which
it is applied shall be a pointer to an object type, or a pointer to a
function type and the result is an lvalue referring to the object or
function to which the expression points. If the type of the expression
is “pointer to T,” the type of the result is “T.”
and:
2 The result of each of the following unary operators is a prvalue.
3 The result of the unary & operator is a pointer to its operand.
Since &a yields a prvalue, &a = 5 is invalid, because &a is not an lvalue. Only modifiable lvalues can appear on the left hand of the built-in assignment operator.
On the other hand, *(&a) yields an lvalue (making it assignable).
&a will return a pointer to a, or the memory address where a is located. The dereference operator * returns the value of the data pointed to by the address. Consider the following code.
int foo = 3;
int* bar = &foo; /// bar points to foo.
printf( "%d\n", *bar ); /// will print 3
printf( "%d\n", *(&foo) ); /// will also print 3
The variable bar points to the memory address where foo is located. By using the dereference operator, you get the value stored in memory at the address contained in bar. The last example combines the two, you get a pointer to foo and immediately dereference it, which returns the value stored in foo
Related
int a = 30;
int& b = (&a)[15];
std::cout << b << std::endl;
I print it , find that this is a random value that doesn't make any sense
What kind of grammar is int& b = (&a)[15]
int& b is a variable. Its name is b and its type is reference to int. type variable_name = expression is syntax for defining and initialising a variable.
& is a unary operator. For fundamental types, it is the addressof operator. Thus &a gives the address of the object referred by a. [] is the subscript operator. It adds the integer operand to the pointer operand, and indirects through the resulting pointer. In this case the pointer operand is a pointer to a, so the result is a reference to the fifteenth sibling of a. b is initialised to refer to that sibling.
Edit:
int a = 30;
Given this context, there is no fiftheenth sibling, and so the behaviour of the program is undefined.
I want to know what is the different between *&aPtr and &*aPtr if replaced * & and & * ?
int a;
int *aptr;
a = 7;
aptr=&a;
cout << &* aPtr<< *&aPtr<< endl;
They have the same value, but *&aPtr is an lvalue that refers to aPtr whereas &*aPtr is a prvalue that has the same value as aPtr.
If the types are primitives (integers, characters, booleans etc.), then they will yield the same value.
A difference may occure if the operators & and * are overloaded for specific class. in this case, depending on the implementation alone - there might be a difference.
One other thing: a corner case can occure if T* t actually points to null:
int* i = nullptr;
*&i; //ok, first takes the address of i, then dereference it, yielding a null pointer again
&*i //wrong, dereference a null pointer, yielding undefined behavior
These unary operators & and * group right to left.
So in this expression
&*aPtr
at first operator * is applied and you get lvalue of a after that operator & is applied and you get rvalue of pointer to a.
Its value is the same as the initial value of aPtr. However you may not write for example
&*aPtr = &a;
while you may write
aPtr = &a;
In this expression
*&aPtr
at first operator & is applied that yields the address of variable aPtr itself. After that operator * is applied and you get again aPtr.
The difference between this expression and the above expression is that you may write
*&aPtr = &a;
because expression *&aPtr yields lvalue of aPtr.
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.
Take this piece of code:
int a;
int *pointer = &a;
int **b = &(&(*pointer));
Would the above set b to the address of pointer or not?
The reason I ask is because *pointer gives the value of a, and the reference of that is the address of a. Is this treated as just the address of a, or is it also treated as pointer.
Does this make sense? Could I do:
&(*pointer) = a;
No. In C, you can only get a pointer to a storage area (which means a variable, an array element, or another pointer; they call those "l-values"), not to any expression. You cannot get a pointer to an expressions that has no defined storage area (like an addition, or the result of a function call). It should be noted however that C++ messes these rules with references, but for the sake of clarity, I'll leave it out.
Pointers aren't magical: in the end, they're just integers. Therefore, when you get the pointer of a pointer, it's just like you were getting the pointer of an integer. It has no more repercussions.
For instance, if you get the pointer to a in your code, you're just copying this address in another variable. Nothing keeps you from changing said variable:
int a;
int* p = &a;
p = NULL;
And doing this, you a will remain unaltered. All you can change about a is its value. Its address is immutable. Anything else would imply that &a = NULL (or any other pointer value) would work, which doesn't.
int **b = &(&(*pointer));
This doesn't, or shouldn't compile.
You can only take the address of an l-value. (See below for a description)
C++03 S5.3.1-2:
The result of the unary & operator is
a pointer to its operand. The operand
shall be an lvalue or a qualifiedid.
In the first case, if the type of the
expression is “T,” the type of the
result is “pointer to T.” In
particular, the address of an object
of type “cv T” is “pointer to cv T,”
with the same cv-qualifiers. For a
qualified-id, if the member is a
static member of type “T”, the type of
the result is plain “pointer to T.” If
the member is a nonstatic member of
class C of type T, the type of the
result is “pointer to member of class
C of type
...and the reference of that is the address of a...
Also you are using the term reference wrong here. & is a symbol that is used for different things. one of those things is to declare references, an unrelated thing is the address of unary operator. The later is not called a reference.
Does this make sense? Could I do: &(*pointer) = a;
An address of a variable, and hence &(*pointer) or equivalently &a are r-values.
You can't assign anything to an r-avlue. Ignoring things like const you can consider an r-value something that must appear on the right hand side. An l-value is kind of like left hand side but really it means it can be stored in a storage location (the difference is because a const object for example can't appear on the left hand side but it is still considered an l-value).
You can't take the address of something twice, so the above code probably won't even compile (have you tried that? What happened?).
In your expression:
*ptr is a lvalue
&(*ptr) is a rvalue
&(&(*ptr)) is an ill-formed expression as you are trying to take the address of an rvalue which is not allowed in C++.
Furthermore,
&(*pointer) = a;
is ill-formed, because the type of the lhs expression is 'int *' where type of rhs expression is 'int'. C++ does not allow converting an 'int' to 'int *'
Would the above set b to the address of pointer or not?
No, it won't. &(*pointer) is the address of a, which is just a number (an r-value), and you can't take the address of or assign to an r-value. So both &(&(*pointer)) and &(*pointer) = a will not compile.
The address of pointer is simply &pointer, so what will work is int **b = &pointer;.
1.No, and that make compile error at int **b = &(&(*pointer));
2.Set b to the address of pointer: int **b = &pointer;
3.&(*pointer) = a; -> NO you cant. &something is constant cant be changed, must be *pointer = a; or pointer = &a;