C中可能存在导致UB的事情。
他们中的大多数都可以这样做,但有几个实现定义的行为更合乎逻辑。让我举个例子:
关于<<
运营商,
如果E1具有带符号类型和非负值,并且E1×2 E2可在结果类型中表示,那么这就是结果值;否则,行为是未定的。
这意味着
signed char r = 0x40;
r <<= 2;
是UB,其中IB将IMO更合乎逻辑。
是否允许实现定义此处发生的事情?
答案 0 :(得分:2)
来自C标准:
符合标准的托管实现应接受任何严格符合的程序......符合要求的实现可能具有扩展(包括附加的 库函数),只要它们不改变任何严格符合的行为 程序
换句话说,实现可以自由地保证特定行为,否则将是未定义的行为。它不能以改变定义的行为的方式来实现。
答案 1 :(得分:2)
问题是:
signed char r = 0x40;
r <<= 2;
不是未定义的行为。
C说:r <<= 2;
相当于
r = r << 2;
唯一差异r
仅评估一次。
r << 2
等同于(int) r << 2
,与<<
相同,整数促销适用于每个操作数。
所以我们实际上有:
r <<= 2;
相当于
r = 0x100;
此赋值也不是未定义的行为。 0x100
在分配之前转换为signed char
,此转换由c99,6.3.1.3p3规定,其中此处的转换是实现定义的。
现在,如果它是未定义的行为,“实现者可以通过提供官方未定义行为的定义来扩充语言”(来自c99 Rationale文档)(这在c99,4.p6中说明)
答案 2 :(得分:1)
ISO C所说的意义上的未定义行为。如果某个实现定义某个特定的行为(在ISO C中未定义),那么这样做是完全有效的。它不符合ISO C标准。
GCC有一些在ISO C中未定义但在GNU C中有效的扩展。取一个函数/ void的大小(sizoof (a_function)
和sizeof(void)
)。
遵循ISO C的主要原因是使代码更具可移植性。因此,如果X的行为未定义(在ISO C中),并且您的实现定义了X的有效行为,则您的代码不可移植其他实现可能没有为X定义任何内容。