一元语义&基于数字文字

时间:2022-01-04 21:43:34

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.

如果你要打印结果,你会得到2010的值。

You have to compile it with -fpermissive or it will stop due to errors.

你必须用- fperative编译它,否则它会因为错误而停止。

4 个解决方案

#1


1  

You cannot apply the unary & operator to an integer literal, because a literal is not an lvalue.

不能将一元和运算符应用到整数文字,因为文字不是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]).

由于操作符优先级的原因,您的代码不会那样做。由于操作符[]比一元&和[5][a]绑定得更紧密,所以[5][a]等价于&(5[a])索引。

Here's a program similar to yours, except that it's valid code, not requiring -fpermissive to compile:

这里有一个类似于您的程序,只是它是有效的代码,不需要- fper来编译:

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

正如在这个问题和我的答案中所解释的,操作符是可交换的(因为它是用加法定义的,而加法是可交换的),所以5[a]等于[5]。因此表达式&5[ptr1]计算arr的元素5的地址。

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.

a的初始化无效,因为a是int*类型,而1990是int类型,并且没有从int到int*的隐式转换。同样,初始化结果是无效的,因为&5[a]类型为int*。显然- fperative会导致编译器违反语言的规则,并允许这些无效的隐式转换。

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

至少在我正在使用的gcc版本中,- fperative选项只对c++和Objective-C有效,对C无效。在C中,gcc允许这样的隐式转换(带有警告)。我强烈建议不要使用这个选项。(您的问题标记为C和c++。请记住,C和c++是两种截然不同的语言,虽然它们是紧密相关的。在这种情况下,他们的行为碰巧相似,但通常最好选择一种或另一种语言。

#2


10  

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

在C中,x [y]和y [x]是相同的。所以&5[a]和&[5]是一样的。

#3


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.

5[a]与&a[5]相同,与a + 5相同。在你的例子中,它是没有定义的行为,因为a指向任何地方。

C11 standard chapter 6.5.6 Additive operators/8 (the same in C++):

C11标准章节6.5.6添加运算符/8(在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.

如果指针操作数和结果点都指向同一数组对象的元素,或数组对象的最后一个元素之后的元素,则计算不产生溢出;否则,行为就没有定义。

#4


3  

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

在C语言中,后缀运算符的优先级总是高于前缀。在第5[a]项下,[]项比&项具有更高的优先级。这意味着在第5和第5[a]中,一元&并没有被应用到“数字文字”中,就像你看起来不正确的那样。它适用于整个5[a]子表达式。即5[a]等于&(5[a])。

As for what 5[a] means - this is a beaten-to-death FAQ. Look it up.

至于5[a]是什么意思,这是一个“打到死”的常见问题。查一下。

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

不,你不需要“用- fper来编译它”(我的编译器告诉我它甚至不知道- fper是什么)。你必须算出这个

int * a = 1990; 

is not legal code in either C or C++. If anything, it requires an explicit cast

不是C或c++中的法律代码。如果有的话,它需要明确的演员阵容。

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

不是您当时碰巧使用的某个特定编译器的模糊切换。这同样适用于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.

最后,即使我们忽略了由5[a]触发的非法代码和未定义的行为,该代码的行为仍然高度依赖于实现。也就是说,答案是否定的,一般来说,你不会得到2010年的结果。

#1


1  

You cannot apply the unary & operator to an integer literal, because a literal is not an lvalue.

不能将一元和运算符应用到整数文字,因为文字不是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]).

由于操作符优先级的原因,您的代码不会那样做。由于操作符[]比一元&和[5][a]绑定得更紧密,所以[5][a]等价于&(5[a])索引。

Here's a program similar to yours, except that it's valid code, not requiring -fpermissive to compile:

这里有一个类似于您的程序,只是它是有效的代码,不需要- fper来编译:

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

正如在这个问题和我的答案中所解释的,操作符是可交换的(因为它是用加法定义的,而加法是可交换的),所以5[a]等于[5]。因此表达式&5[ptr1]计算arr的元素5的地址。

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.

a的初始化无效,因为a是int*类型,而1990是int类型,并且没有从int到int*的隐式转换。同样,初始化结果是无效的,因为&5[a]类型为int*。显然- fperative会导致编译器违反语言的规则,并允许这些无效的隐式转换。

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

至少在我正在使用的gcc版本中,- fperative选项只对c++和Objective-C有效,对C无效。在C中,gcc允许这样的隐式转换(带有警告)。我强烈建议不要使用这个选项。(您的问题标记为C和c++。请记住,C和c++是两种截然不同的语言,虽然它们是紧密相关的。在这种情况下,他们的行为碰巧相似,但通常最好选择一种或另一种语言。

#2


10  

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

在C中,x [y]和y [x]是相同的。所以&5[a]和&[5]是一样的。

#3


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.

5[a]与&a[5]相同,与a + 5相同。在你的例子中,它是没有定义的行为,因为a指向任何地方。

C11 standard chapter 6.5.6 Additive operators/8 (the same in C++):

C11标准章节6.5.6添加运算符/8(在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.

如果指针操作数和结果点都指向同一数组对象的元素,或数组对象的最后一个元素之后的元素,则计算不产生溢出;否则,行为就没有定义。

#4


3  

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

在C语言中,后缀运算符的优先级总是高于前缀。在第5[a]项下,[]项比&项具有更高的优先级。这意味着在第5和第5[a]中,一元&并没有被应用到“数字文字”中,就像你看起来不正确的那样。它适用于整个5[a]子表达式。即5[a]等于&(5[a])。

As for what 5[a] means - this is a beaten-to-death FAQ. Look it up.

至于5[a]是什么意思,这是一个“打到死”的常见问题。查一下。

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

不,你不需要“用- fper来编译它”(我的编译器告诉我它甚至不知道- fper是什么)。你必须算出这个

int * a = 1990; 

is not legal code in either C or C++. If anything, it requires an explicit cast

不是C或c++中的法律代码。如果有的话,它需要明确的演员阵容。

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

不是您当时碰巧使用的某个特定编译器的模糊切换。这同样适用于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.

最后,即使我们忽略了由5[a]触发的非法代码和未定义的行为,该代码的行为仍然高度依赖于实现。也就是说,答案是否定的,一般来说,你不会得到2010年的结果。