【发布时间】:2017-09-04 01:59:46
【问题描述】:
在 C89 标准中,我找到了以下部分:
3.2.2.1 左值和函数指示符
除非它是 sizeof 运算符、一元 & 运算符、++ 运算符、-- 运算符或 . 的左操作数的操作数。运算符或赋值运算符,不具有数组类型的左值将转换为存储在指定对象中的值(并且不再是左值)。如果左值具有限定类型,则该值具有左值类型的非限定版本;否则该值具有左值的类型。 如果左值的类型不完整且没有数组类型,则行为未定义。
如果我没看错的话,它允许我们创建一个lvalue 并在其上应用一些运算符,这会编译并在运行时导致未定义的行为。
问题是,我想不出一个“不完整类型的左值”的例子,它可以通过编译器的语义检查并触发undefined behavior。
考虑左值是
左值是指定对象的表达式(具有对象类型或除 void 以外的不完整类型)。
那个不完整的类型是
类型分为对象类型(描述对象的类型)、函数类型(描述函数的类型)和不完整类型(描述对象但缺少确定其大小所需信息的类型)。
我试过的一个失败的程序:
struct i_am_incomplete;
int main(void)
{
struct i_am_incomplete *p;
*(p + 1);
return 0;
}
并得到以下错误:
error: arithmetic on a pointer to an incomplete type 'struct i_am_incomplete'
*(p + 1);
~ ^
谁能想到这方面的例子? “不完整类型的左值”示例,可以通过编译器的语义检查并触发undefined behavior。
更新:
正如@algrid 在答案中所说,我误解了undefined behavior,其中包含compile error 作为选项。
也许我要扯皮了,我仍然想知道这里的潜在动机是更喜欢undefined behavior 而不是disallowing an lvalue to have an incomplete type。
【问题讨论】:
-
什么例子?您已经提供了一个示例。不清楚你在问什么。注意您的问题措辞有误。 语法上是可能的,但语义上是不可能的。如果它在语法上是不可能的,你就会得到一个语法错误。
-
要进行任何指针运算,编译器必须知道底层数据的大小。另一方面,将指针保留为变量不需要有关数据的知识。因此,您几乎可以将指针分配给不完整的数据类型,但仅此而已。
-
@EJP 你是对的,它应该是语义上的东西。我正在修复它。那么,如果它在语义上是不可能的,那么这条规则的意图是什么?
-
@EJP 一个“不完整类型的左值”的例子,它可以通过编译器的语义检查。或者规则的意图“如果左值的类型不完整并且没有数组类型,则行为未定义。”
-
我认为 OP 的预期问题是:“是否有可能有一个没有违反约束的程序对不完整类型的左值执行左值转换?”
标签: c language-lawyer undefined-behavior lvalue incomplete-type