C99中与常量表达式相关的未定义行为的含义和示例

C99中与常量表达式相关的未定义行为的含义和示例,c,language-lawyer,undefined-behavior,c99,C,Language Lawyer,Undefined Behavior,C99,我不理解C99中与常量表达式相关的未定义行为 例如: 要求为整型常量表达式的表达式 没有整数类型;具有非整数的操作数 常量、枚举常量、字符常量、sizeof 结果为整数常量或立即强制转换的表达式 浮动常数;或包含强制转换(从操作数外部转换为sizeof 运算符)而不是将算术类型转换为整数类型 (6.6) 我找不到这样的例子 此外,我不明白为什么常量表达式(在翻译时计算)不会成为在运行时计算的表达式(而不是UB)。这是从资料性附录J中引用的。要找到实际的规范性文本,您必须进入附录J所指的部分,在这

我不理解C99中与常量表达式相关的未定义行为

例如:

要求为整型常量表达式的表达式 没有整数类型;具有非整数的操作数 常量、枚举常量、字符常量、sizeof 结果为整数常量或立即强制转换的表达式 浮动常数;或包含强制转换(从操作数外部转换为sizeof 运算符)而不是将算术类型转换为整数类型 (6.6)

我找不到这样的例子

此外,我不明白为什么常量表达式(在翻译时计算)不会成为在运行时计算的表达式(而不是UB)。

这是从资料性附录J中引用的。要找到实际的规范性文本,您必须进入附录J所指的部分,在这种情况下,整数常量表达式C99的定义为6.6:

整数常量表达式(99)应为整数类型,且只能有操作数 它们是整数常量、枚举常量、字符常量、sizeof 结果为整数常量的表达式,以及作为 强制转换的立即操作数

在我看来,这段文字是不言自明的。也就是说:当其他地方的语法或规范性文字需要一个整型常量表达式时,在这样的位置放置的任何东西都必须满足上面引用的部分,或者它不是整型常量表达式,而是未定义的行为。(违反ISO C规范性文本中的“应”要求始终是不可接受的。)

我希望编译器能够很好地给出错误,因为这是编译时

例如,这是无效的,因为具有静态存储持续时间的数组声明要求大小为整数常量表达式:

int a=1;
static int x [a];

类似地,
intx[1+1.0]将无效,但
intx[1+(int)1.0]正常。

根据N1570 6.6p10,“一个实现可以接受其他形式的常量表达式。”通常,允许一个实现拒绝一个程序,但也允许它接受的情况被归类为未定义行为。虽然指定给定以下内容的实现可能会有所帮助(在文件范围内):

如果在运行时执行指定的转换和减法,则需要拒绝程序,或者表现为将
sz
初始化为与计算值匹配的值,此类构造通常需要链接器支持,编译器可能无法确定链接器支持什么构造,或者如果代码使用不支持的构造,它会做什么

该标准不使用术语“未定义的行为”来纯粹指代错误的构造,但也将其应用于不可移植的构造,这些构造在某些实现中可能不受支持或错误,但在其他实现中是正确的。标准的作者指出,未定义的行为,除其他外,通过允许实现定义超出标准要求的行为,识别了“一致性语言扩展”的潜在领域。从这个角度来看,将整型常量表达式的非标准形式的处理归类为未定义的行为可以使编译器在实用和有用时支持此类结构,而不会对某些实现可能无法满足的此类结构的行为强加要求


回到前面的示例,编译器可能会将
&y
&x
之间的差异计算为两个对象各自数据段内偏移量之间的差异。只有当对象恰好在同一个翻译单元中定义时,这种计算才可能有用,并且如果对象没有定义,则可能产生无意义的值,而不必发出诊断。然而,编译器无法知道对象是否定义在同一个翻译单元中,如果两个外部定义的对象是在同一个编译单元中定义的,则标准将没有定义其行为有意义的代码的概念,但如果它们不是在同一编译单元中定义的,则没有定义。根据标准管辖范围以外的标准,在某些情况下实施会定义行为的标准术语,但在其他情况下不会定义。该术语是“未定义的行为”。

不加评论地理解否决票。瑞银在C语言中总是很棘手,为什么这个问题不合法?我也不理解反对票,尽管你可以在这样的问题上加上标签,以澄清你对语言定义而不是实际用途感兴趣。谢谢。我读过你引用的那一节,但没有发现它是不言自明的。你的例子使它更具说服力clear@GuillaumePetitjean我认为他们的目标是,如果你在C所期望的地方写的不是整型常量表达式,那就是UB。C99的基本原理也没有提供太多的解释,只是“整数常量表达式必须只包含在转换时可以知道的数字,并且运算符没有任何副作用。”@Lundin:C标准明确允许实现接受超出强制范围的形式。我认为我们的目标不是那些不是整型常量表达式的构造,而是那些特定实现可能会将其视为整型常量表达式的构造,尽管该标准并不要求这些构造。根据标准管辖范围以外的标准,某些此类结构在某些情况下可能会表现出有用的行为,但在另一些情况下可能表现出不可预测的行为,因此,该标准不能在不影响其实用性的情况下真正指定任何有关其行为的有意义的内容。@supercat 6.6p10中的文本很可能不是针对整型常量表达式,而是针对浮点、com等其他形式
int x,y;
int sz = (uintptr_t)&y - (uintptr_t)&x;