涉嫌采访的问答在这里.
以下代码是否会编译(在C中)?
#define X 8;
int main(void)
{
++X; // will this line compile?
}`
Run Code Online (Sandbox Code Playgroud)
我不是C的专家,但我知道一些C++并认为:当然不是,你不能增加数字8,它是一个右值.当然,预处理程序替换X与8尝试编译之前,并且当它尝试编译,它就会失败正是由于这个原因.然后,我是一个阅读面试问题的网站,所以我想谁知道...
这是给出的解释:
"严格来说,前缀(或后缀)增量运算符的操作数必须是一个不可修改的左值.现在我们知道左值是什么,我们必须问自己X是否是左值.X是一个宏,这意味着它不能识别内存中的位置 - 宏通过预处理器使用简单的文本替换.因为宏不存在于内存区域,所以它们不是左值.这意味着X不能用作前缀增量的操作数因此,上面显示的代码将无法编译."
这个解释是否像我认为的那样是无聊的?
你上面能找到多少错误?我想也许这应该是面试问题......
这很有趣:
"直观地说,你可能会说上面的代码无法编译 - 如果不确切知道原因.但是,在面试的情况下,你会被期望提供一些像上面给出的那样的推理.简单的是或否答案刚赢了"在接受采访时削减它." (!)
Ste*_*sop 10
给出的解释是不正确的:
X是一个宏,这意味着它不能识别内存中的位置 - 宏通过预处理器使用简单的文本替换.
正是因为宏只是简单的文本替换,它们可以扩展到左值,或者其他任何东西.例如:
int x;
#define X x
int main() {
++X;
}
Run Code Online (Sandbox Code Playgroud)
没关系 这是真的,宏本身不具有记忆的地方,但是这无关紧要是否++X;良好形成-,因为++X;并不意味着,"增加宏观X",它的意思是"扩展宏X,然后粘++在正面,;背面,对结果进行句法和语义分析".
关于"宏"的解释是什么,应该说整数常量.8不是左值,这就是重要的事情.
有了这个改变,解释就可以了[编辑 - 正如Chris在评论中指出的那样,它仍然不行,它写道"前缀(或后缀)增量运算符的操作数必须是一个不可修改的左值":应该读取"修改"]
这个解释是否像我认为的那样是无聊的?
是.
"严格来说,前缀(或后缀)增量运算符的操作数必须是不可修改的左值...
什么?非修改的左值是一样的东西const int n;-你可以把它的地址(通过&),但你不能分配给它(通过=,+=或++).你不能增加一些不可修改的东西.
引用标准(6.5.3.1第1段):
pre fi x递增或递减运算符的操作数应具有合格或不合格的实数或指针类型,并且应为可修改的左值.
咳咳.
X是一个宏,这意味着它不能识别内存中的位置 - 宏通过预处理器使用简单的文本替换.
这是假的.C语言中不存在宏*.它们是预处理器的一部分,它没有左值,右值,表达式或内存的概念.这个特定的宏扩展为一个整数常量,它是一个rvalue,但宏本身与上面的任何一个都没有关系.请参阅史蒂夫杰索普的回答,其中一个宏是左值的反例.
正确的答案是语句扩展为++8,因为8它是一个rvalue,它不能用作++(以任何一种形式)的参数,因此它不会编译.此外,根据您是否打算将此代码编译为C89或C99,main如果没有显式return值,则可能会给出未定义的行为.
*如果这将成为公认的答案,我想我应该澄清这一点:预处理器是 C编程语言的一部分.它在C标准中指定,并且编译器必须实现预处理才能成为C编译器.但是,C语言(即语法,语义,库等)不与预处理器交互 - 一旦你进入开始处理左值和右值的阶段,预处理器早就完成了所有宏都完全展开.该宏本身不具备的语法任何地方,因为它们不是金"的语言." 关于在这里使用"语言"这个词是否具有误导性的问题存在争议(在Steve Jessop的回答中),我同意他的看法,我找不到更好的词来代替.