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.

+3


source to share


4 answers


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.)

+1


source


In C, x [y] and y [x] are identical. Thus & 5 [a] is the same as & a [5].



+10


source


&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.

+5


source


"... 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

.

+3


source







All Articles