提问人:Aaron Linnell 提问时间:6/19/2023 最后编辑:LundinAaron Linnell 更新时间:6/19/2023 访问量:94
基于这种有趣的差异,C声明实际上是如何解析的?
How are C declarations actually parsed, based on this interesting discrepancy?
问:
将声明和赋值组合在一起是很常见的:
int beans = a * 2;
或者分开,像这样
int beans;
beans = a * 2;
我目前的理解是,豆子可以被赋值,因为它是一个左值;它具有可以写入的存储。不能赋值 rvalue,因为它只是一个带有值的表达式,没有存储。因此,允许这样做:a * 2
int beans;
(beans) = a * 2;
事实上,任何左值赋值的左操作数都应该有效。现在,这似乎表明这是一个表达式,也是一个左值。但是,这是不允许的:int beans;
(int beans) = a * 2;
就 C 解析器的设计方式而言,这表明声明不仅仅是一个带有左值的表达式。这是怎么回事?
答:
声明
beans = a * 2;
包含许多表达式。
主要表达式是赋值本身:.这反过来又包含两个子表达式:和 .乘法表达式本身具有子表达式:和 。beans = a * 2
beans
a * 2
a
2
所有表达式都可以用括号括起来,这意味着整个语句可能如下所示:
(beans) = ((a) * (2));
这里所有的子表达式都用括号括起来。
现在我们来谈谈定义:
int beans;
这不是一个表达方式。它不包含任何子表达式。它不能作为一个整体括起来。
另一方面,初始化的定义:
int beans = a * 2;
do 包含一个带有子表达式的表达式。那是在 .所以我们可以把它写成:=
int beans = ((a) * (2));
但同样,变量声明部分不是表达式,不能用括号括起来。
另请注意,在定义中不是赋值。这是初始化。这两个不同的术语表明存在语义差异。=
正如乔纳森·莱夫勒(Jonathan Leffler)的评论中提到的。声明的声明器部分可以用括号括起来。
对于一个简单的声明,例如
int beans;
使用它真的没有意义。但是对于指向函数的指针或指向数组的指针之类的东西,它有很大的不同。
例:
int *foo(int x);
它声明了一个函数,该函数接受一个参数并返回指向 的指针。与以下内容进行比较:int
int
int (*foo)(int x);
它声明了一个变量,该变量是指向函数的指针。该函数接受一个参数,并返回一个值。int
int
评论
int (beans);
int (beans) = 3;
int ((((beans)))) = { 3 };
上一个:在赋值重载期间按引用返回
评论
=
int beans = a * 2;
=
=
int a[3] = {1, 2, 3};