什么是一元 - &在这儿干?
int * a = 1990;
int result = &5[a];
如果您要打印result
,您将获得2010年的价值。
您必须使用-fpermissive
进行编译,否则会因错误而停止。
答案 0 :(得分:10)
在C中,x [y]和y [x]是相同的。因此& 5 [a]与& a [5]相同。
答案 1 :(得分:5)
&5[a]
与&a[5]
相同,与a + 5
相同。在你的情况下,它是未定义的行为,因为a
指向无处。
C11标准章节6.5.6 Additive operators/8
(在C ++中相同):
如果两个指针都有 操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素 数组对象的元素,评估不得产生溢出;否则, 行为未定义。
答案 2 :(得分:3)
" ...一元&
关于数字文字"?
C中的后缀运算符始终具有比前缀1更高的优先级。如果是&5[a]
,则[]
的优先级高于&
。这意味着在&5[a]
中,一元&
未应用于"数字文字"因为你似乎错误地相信。它适用于整个5[a]
子表达式。即&5[a]
相当于&(5[a])
。
至于5[a]
的含义 - 这是一个被打死的FAQ。查一查。
不,你没有"用-fpermissive
"编译它。 (我的编译器告诉我它甚至不知道-fpermissive
是什么)。你必须弄清楚这个
int * a = 1990;
不是C或C ++中的合法代码。如果有的话,它需要一个明确的演员
int * a = (int *) 1990;
目前您正在使用的某些特定编译器并不是一些模糊的开关。这同样适用于int result = &5[a]
中的另一个非法初始化。
最后,即使我们忽略了非法代码和由5[a]
触发的未定义行为,此代码的行为仍将高度依赖于实现。即答案是否定的,一般情况下,您不会在2010
中获得result
。
答案 3 :(得分:1)
您无法将一元&
运算符应用于整数文字,因为文字不是左值。
由于运算符优先级,您的代码不会这样做。由于索引运算符[]
的绑定比一元&
更紧密,因此&5[a]
等同于&(5[a])
。
这是一个类似于你的程序,除了它是有效的代码,不需要-fpermissive
编译:
#include <stdio.h>
int main(void) {
int arr[6];
int *ptr1 = arr;
int *ptr2 = &5[ptr1];
printf("%p %p\n", ptr1, ptr2);
}
如this question和my answer中所述,索引运算符是可交换的(因为它是根据加法定义的,并且加法是可交换的),因此5[a]
等同于{{1 }}。因此,表达式a[5]
计算&5[ptr1]
的元素5的地址。
在你的计划中:
arr
int * a = 1990;
int result = &5[a];
的初始化无效,因为a
的类型为a
且int*
的类型为1990
,并且int
没有隐式转换{1}}到int
。同样,int*
的初始化无效,因为result
的类型为&5[a]
。显然int*
会导致编译器违反语言规则并允许这些无效的隐式转换。
至少在我正在使用的gcc版本中,-fpermissive
选项仅对C ++和Objective-C有效,而不适用于C.在C中,gcc允许这样的隐式转换(带警告) 。我强烈建议不使用此选项。 (你的问题被标记为C和C ++。请记住,C和C ++是两种不同的,虽然密切相关的语言。在这种情况下它们的行为似乎相似,但通常最好选择一种语言或另一种语言。)< / p>