实现可以指定未定义的行为
3.4.1
1实现定义的行为
未指定的行为,其中每个实现记录了如何进行选择
实现是否可以指定,在未定义的行为是可能的结果的情况下,实现定义的行为是未定义的行为?
例如:
6.3.1.3有符号和无符号整数
3否则,新类型已签名且值无法在其中表示; 结果是实现定义的,或者引发实现定义的信号。
因此,只要记录在案,这个结果是否可以由实现未定义并导致未定义的行为,或者它必须具有该实现的定义结果?
不,从语义上说这是不可能的。 未定义的行为是术语陈述的行为,未由标准定义的行为。 如果标准请求实现定义的行为,它会显式请求实现指定发生特定错误时的操作。
未定义的行为
行为,在使用不可移植或错误的程序结构或错误数据时,本国际标准不对此要求
所以一个实现可以说“在那个和那种情况下这个实现提出了一个模糊的信号”但它不能说“在那个和那种情况下我们不会告诉你我们在做什么” 。
不要将未定义的行为误解为会发生的事情,甚至是可以定义的事物。
您可以在C基本原理中找到“实施定义”意图的更详细说明 – 不是标准文件本身 ,而是一个很好的参考。
在第1.6章术语的定义中 :
实现定义的行为使实现者可以自由选择适当的方法,但需要向用户解释此选择。 指定为实现定义的行为通常是用户可以基于实现定义做出有意义的编码决策的行为。 在决定实施定义应该有多广泛时,实施者应该牢记这个标准。 与未指定的行为一样,仅仅无法转换包含实现定义的行为的源不是一个充分的响应。
您无法根据未定义的行为做出“合理的编码决策”。
C FAQ(再次,不是标准,但是一个众所周知的参考)也很清楚 :
implementation-defined:实现必须选择一些行为; 它可能无法编译该程序。 ( 使用该构造的程序不正确。 )必须记录选择。 标准可以指定一组允许的行为,可以从中选择,也可以不强加任何特定要求
未指定和实现定义的行为都不是错误 – 编译器不能使转换失败。 它们旨在提供实现选项,以便为目标环境生成最佳代码。
将整数分配给较小的类型是一件奇怪的事情,因为标准清楚地认识到某些实现可能陷阱,但是 – 唯一的 – 它要求陷阱遵守信号规则; 在这里强制要求但不在其他地方的决定有点好奇,因为在许多情况下它会阻碍本来可能是直接的优化 – 替换类型短于int
有符号整数变量,并且其地址永远不会被采用, int
。
尽管如此,无论出于何种原因,该标准的作者都不遗余力地禁止这种优化。 [注意:如果我负责标准,我会指定对较短整数类型的显式强制转换会产生一个值,当转换为相同大小的无符号类型时,将产生与每次直接转换值时相同的结果存在这样的值,但是直接对没有强制转换的左值的超大值的存储不会因此受到限制; 虽然我没有写标准。
具有讽刺意味的是,实际上:给定:
uint64t signedpow(int32_t n, uint32_t p) { uint64_t result; while(p--) { n*=n; result+=n; } return result; } uint64t unsignedpow(uint32_t n, uint32_t p) { uint64_t result; while(p--) { n*=n; result+=n; } return result; }
在int
为32位的平台上,后者将为n
和p
所有值定义语义,而前者不会,但在int
为64位的平台上,反之则为真。 一个典型的64位平台的编译器不希望在其他一些定义的行为上浪费代码,标准需要在每次乘法后屏蔽和签名扩展有符号的n
,但编译器可以使用一些无符号值做任何它想做的事情,包括回到过去并假装没有任何实现会承诺总是以与模运算一致的方式执行半尺寸无符号乘法。
根据C11
标准,第3.4.1章,
实现定义的行为
未指定的行为,其中每个实现记录了如何进行选择
因此,每个实现都必须做出选择。 否则,它将不符合要求 。 因此,我们可以说,它必须具有该实现的定义结果。 这可以是以下任何一个
- 特定于该实现的已定义行为,如果遇到该指令,将执行该行为。
- 一个定义的信号,如果遇到这种情况将会被劫持。 (大多数情况下,说不能处理。)
有关:
- 来自
C99
理由文件 ,第3章,( 强调我的 )
实现定义的行为使实现者可以自由选择适当的方法,但需要向用户解释此选择。 指定为实现定义的行为通常是用户可以基于实现的定义做出有意义的编码决策的行为 。 在决定实施定义应该有多广泛时,实施者应该牢记这个标准。 与未指定的行为一样,只是无法转换包含实现定义的行为的源不是一个充分的响应。
现在,没有人可以根据未定义的行为采取“有意义的编码决策”。
- 来自C FAQ ,问题11.33,
implementation-defined:实现必须选择一些行为; 它可能无法编译该程序。 (使用该构造的程序不正确。)必须记录选择。 标准可以指定一组允许的行为,可以从中选择,也可以不强加任何特定要求。
第一句包含必须 ,与我之前在答案中提到的相同。