What is the unary-& doing here?
int * a = 1990;
int result = &5[a];
If you were to print result
you would get the value 2010.
You have to compile it with -fpermissive
or it will stop due to errors.
What is the unary-& doing here?
int * a = 1990;
int result = &5[a];
If you were to print result
you would get the value 2010.
You have to compile it with -fpermissive
or it will stop due to errors.
In C, x [y] and y [x] are identical. So &5[a] is the same as &a[5].
&5[a]
is the same as &a[5]
and the same as a + 5
. In your case it's undefined behavior because a
points to nowhere.
C11 standard chapter 6.5.6 Additive operators/8
(the same in C++):
If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
"...unary &
on numeric literal"?
Postfix operators in C always have higher priority than prefix ones. In case of &5[a]
, the []
has higher priority than the &
. Which means that in &5[a]
the unary &
is not applied to "numeric literal" as you seem to incorrectly believe. It is applied to the entire 5[a]
subexpression. I.e. &5[a]
is equivalent to &(5[a])
.
As for what 5[a]
means - this is a beaten-to-death FAQ. Look it up.
And no, you don't have "to compile it with -fpermissive
" (my compiler tells me it doesn't even know what -fpermissive
is). You have to figure out that this
int * a = 1990;
is not legal code in either C or C++. If anything, it requires an explicit cast
int * a = (int *) 1990;
not some obscure switch of some specific compiler you happened to be using at the moment. The same applies to another illegal initialization in int result = &5[a]
.
Finally, even if we overlook the illegal code and the undefined behavior triggered by that 5[a]
, the behavior of this code will still be highly implementation-dependent. I.e. the answer is no, in general case you will not get 2010
in result
.
You cannot apply the unary &
operator to an integer literal, because a literal is not an lvalue.
Due to operator precedence, your code doesn't do that. Since the indexing operator []
binds more tightly than unary &
, &5[a]
is equivalent to &(5[a])
.
Here's a program similar to yours, except that it's valid code, not requiring -fpermissive
to compile:
#include <stdio.h>
int main(void) {
int arr[6];
int *ptr1 = arr;
int *ptr2 = &5[ptr1];
printf("%p %p\n", ptr1, ptr2);
}
As explained in this question and my answer, the indexing operator is commutative (because it's defined in terms of addition, and addition is commutative), so 5[a]
is equivalent to a[5]
. So the expression &5[ptr1]
computes the address of element 5 of arr
.
In your program:
int * a = 1990;
int result = &5[a];
the initialization of a
is invalid because a
is of type int*
and 1990
is of type int
, and there is no implicit conversion from int
to int*
. Likewise, the initialization of result
is invalid because &5[a]
is of type int*
. Apparently -fpermissive
causes the compiler to violate the rules of the language and permit these invalid implicit conversions.
At least in the version of gcc I'm using, the -fpermissive
option is valid only for C++ and Objective-C, not for C. In C, gcc permits such implicit conversions (with a warning) anyway. I strongly recommend not using this option. (Your question is tagged both C and C++. Keep in mind that C and C++ are two distinct, though closely related, languages. They happen to behave similarly in this case, but it's usually best to pick one language or the other.)