Semantics of unary & on numeric literal
What is unary & doin 'here?
int * a = 1990;
int result = &5[a];
If you want to print result
, you will get 2010.
You have to compile it with -fpermissive
or it will stop due to errors.
You cannot apply a unary operator &
to an integer literal because a literal is not an lvalue.
Due to operator precedence, your code doesn't do this. Since the indexing operator []
is more rigidly bound than unary &
, it is &5[a]
equivalent &(5[a])
.
Here the program is similar to yours, except that it is valid for code without requiring it -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 (since it is defined in terms of addition and addition is commutative), so it is 5[a]
equivalent a[5]
. Thus, the expression &5[ptr1]
evaluates to the address of element 5 arr
.
In your program:
int * a = 1990;
int result = &5[a];
the initialization a
is invalid because it a
is of type int*
and 1990
is of type int
, and there is no implicit conversion from int
to int*
. Likewise, the initialization result
is invalid because it &5[a]
has a type int*
. Seemingly -fpermissive
causing the compiler to break the language rules and allow these invalid implicit conversions.
At least in the version of gcc I am using, the parameter -fpermissive
is only valid for C ++ and Objective-C, not C. In C, gcc allows such implicit conversions (with a warning) anyway. I highly recommend not using this option. (Your question is tagged in both C and C ++. Keep in mind that C and C ++ are two different, albeit closely related, languages. In this case, they behave the same, but usually better just choose one or the other language.)
In C, x [y] and y [x] are identical. Thus & 5 [a] is the same as & a [5].
&5[a]
matches &a[5]
and matches a + 5
. In your case, this behavior is undefined because it a
points to nowhere.
Standard C11 chapter 6.5.6 Additive operators/8
(same in C ++):
If the operand pointer and the result point to elements of the same array object, or one after the last element of the array object, the evaluation shall not overflow; otherwise, the behavior is undefined.
"... unary &
in numeric literal"?
Postfix operators in C always take precedence over prefix operators. In case &5[a]
[]
has a higher priority than &
. This means that &5[a]
unary &
does not apply to a "numeric literal" as you seem to be wrongly thinking. It applies to the entire subexpression 5[a]
. That is, it is &5[a]
equivalent &(5[a])
.
Which means 5[a]
- this is a cue to death FAQ . Take a look.
And no, you don't have to "compile it with -fpermissive
" (my compiler tells me it doesn't even know what it is -fpermissive
). You must understand what it is
int * a = 1990;
is not legal C or C ++ code. If anything, it requires explicit casting
int * a = (int *) 1990;
not some obscure switch for a particular compiler that you are currently using. The same applies to other illegal initialization in int result = &5[a]
.
Finally, even if we omit invalid code and undefined behavior caused by it 5[a]
, the behavior of that code will still be highly implementation-dependent. That is, the answer is no, in general you will not get 2010
in result
.