所谓的面试问答here。
下面的代码可以编译(用C编写)吗?
#define X 8;
int main(void)
{
++X; // will this line compile?
}`我不是C语言专家,但我知道一些C++,并认为:当然不是,你不能递增数字8,它是一个右值。当然,在尝试编译之前,预处理器会将X替换为8,而当它确实尝试编译时,就会因为这个原因而失败。然后,我是一个阅读面试问题网站的人,所以我想,谁知道……
下面是给出的解释:
严格地说,前缀(或后缀)增量运算符的操作数必须是不可修改的左值。既然我们知道了左值是什么,我们必须问自己X是否是左值。X是宏,这意味着它不能标识内存中的某个位置-宏通过预处理器使用简单的文本替换。因为宏不存在于内存区域中,所以它们不是左值。这意味着X不能用作前缀增量运算符的操作数。因此,上面显示的代码将无法编译。
这个解释是不是像我想的那样是胡说八道?
你能在上面找到多少错误?我想也许这应该是面试的问题。
这很有趣:
“直觉上,你可能会说上面的代码不能编译--而不知道确切的原因。然而,在面试中,你会被要求提供一些类似上面给出的推理。简单的是或否的答案在面试中是不会起作用的。”(!)
发布于 2011-08-16 16:56:31
这个解释是不是像我想的那样是胡说八道?
是。
“严格地说,前缀(或后缀)增量运算符的操作数必须是不可修改的左值...
什么?不可修改的左值类似于const int n; -您可以(通过&)获取它的地址,但不能(通过=、+=或++)对其赋值。你不能增加一些不可修改的东西。
引用该标准(6.5.3.1第1段):
前fix递增或递减运算符的操作数应具有限定实数或不限定实数或指针类型,并且应为modifiable lvalue。
啊哈。
X是一个宏,这意味着它不能识别内存中的位置-宏通过预处理器使用简单的文本替换。
这是假的。宏在C语言中不存在*。它们是预处理器的一部分,预处理器没有左值、右值、表达式或内存的概念。这个特定的宏将扩展为一个整数常量,这是一个右值,但是宏本身与上面的任何内容都没有任何关系。有关宏是左值的反例,请参见Steve Jessop's answer。
正确的答案是,该语句扩展为++8,并且由于8是一个右值,因此它不能用作++的参数(以这两种形式),因此它将不会编译。此外,根据您希望将此代码编译为C89还是C99,如果不使用显式的return值来保留main,则可能会产生未定义的行为。
*如果这将是公认的答案,我想我应该澄清这一点:预处理器是C编程语言的一部分。它是在C标准中指定的,编译器必须实现预处理才能成为C编译器。然而,C“语言”(即语法、语义、库等)不与预处理器交互-一旦你到达开始处理左值和右值的阶段,预处理器早就已经完成了,所有的宏都被完全扩展了。宏本身在语法中没有任何位置,因为它们不是“语言”的一部分。有一些争论(在Steve Jessop的回答中)关于这里使用“语言”这个术语是否具有误导性,我同意他的观点,我只是找不到更好的词来代替。
发布于 2011-08-16 16:50:31
给出的解释是错误的:
X是一个宏,这意味着它不能识别内存中的位置-宏通过预处理器使用简单的文本替换。
正是因为宏只是简单的文本替换,所以它们可以扩展为左值,也可以扩展为其他任何值。例如:
int x;
#define X x
int main() {
++X;
}没问题。的确,宏本身在内存中没有一席之地,但这与++X;是否格式良好无关,因为++X;并不意味着“增加宏X",它的意思是”扩展宏X,然后将++放在前面,;放在后面,并对结果执行语法和语义分析“。
关于“宏”的解释应该是关于整数常量的。8不是左值,这才是最重要的。
有了这个改变,解释是OK编辑--就像克里斯在评论中指出的那样,它仍然不是OK,它写道“前缀(或后缀)增量运算符的操作数必须是non-modifiable左值”:应该是"modifiable“
发布于 2011-08-16 16:44:03
由于完全相同的原因,它不会编译:
8 = 8+1;不会编译。
你不能修改(这里是增量)一个常量。
https://stackoverflow.com/questions/7075565
复制相似问题