实现是否可以指定未定义的行为
Can an implementation specify undefined behavior
3.4.1
1 implementation-defined behavior
unspecified behavior where each implementation documents how the choice is made
在可能出现未定义行为的情况下,实现是否可以指定实现定义的行为是未定义行为?
例如:
6.3.1.3 Signed and unsigned integers
3 Otherwise, the new type is signed and the value cannot be represented in it; either the
result is implementation-defined or an implementation-defined signal is raised.
因此,只要记录在案,该结果是否会被实现未定义并导致未定义的行为,或者它必须具有该实现的已定义结果?
根据 C11
标准,第 3.4.1 章,
implementation-defined behavior
unspecified behavior where each implementation documents how the choice is made
因此,每个实现都必须做出选择。否则,它不会符合。因此,我们可以说,它 必须 具有针对该实现的定义结果。可以是以下任何一种
- 一个定义的行为,特定于该实现,如果遇到指令,将执行该行为。
- a defined 信号,如果遇到指令,将发出信号。 (多半是说处理不了。)
相关:
- 来自
C99
Rationale Document,第 3 章,(强调我的)
Implementation-defined behavior gives an implementor the freedom to choose the appropriate approach, but requires that this choice be explained to the user. Behaviors designated as implementation-defined are generally those in which a user could make meaningful coding decisions based on the implementation’s definition. Implementors should bear in mind this criterion when deciding how extensive an implementation definition ought to be. As with unspecified behavior, simply failing to translate the source containing the implementation defined behavior is not an adequate response.
现在,没有人可以根据未定义的行为做出“有意义的编码决策”。
- 来自 C FAQ,问题 11.33,
implementation-defined: The implementation must pick some behavior; it may not fail to compile the program. (The program using the construct is not incorrect.) The choice must be documented. The Standard may specify a set of allowable behaviors from which to choose, or it may impose no particular requirements.
第一句是必须,和我之前回答的一样
您可以在 C 基本原理 中找到 "implementation defined" 的更详细解释 - 而不是标准文档 本身 ,但很好的参考。
在第 1.6 章中 Definition of terms:
Implementation-defined behavior gives an implementor the freedom to choose the appropriate approach, but requires that this choice be explained to the user. Behaviors designated as implementation-defined are generally those in which a user could make meaningful coding decisions based on the implementation definition. Implementors should bear in mind this criterion when deciding how extensive an implementation definition ought to be. As with unspecified behavior, simply failing to translate the source containing the implementation-defined behavior is not an adequate response.
你不能"reasonable coding decision"基于未定义的行为。
C 常见问题解答(同样,不是标准,而是众所周知的参考)是 quite clear too:
implementation-defined: The implementation must pick some behavior; it may not fail to compile the program. (The program using the construct is not incorrect.) The choice must be documented. The Standard may specify a set of allowable behaviors from which to choose, or it may impose no particular requirements
未指定和实现定义的行为都不是错误 - 编译器不会使翻译失败。它们旨在提供实现选项,以便为目标环境生成最佳代码。
不,从语义上讲这是不可能的。未定义的行为是术语所述,标准未定义的行为。如果标准要求实现定义的行为,它会明确要求实现指定发生特定错误时要执行的操作。
undefined behavior
behavior, upon use of a nonportable or erroneous program construct or
of erroneous data, for which this International Standard imposes no
requirements
所以一个实现可以说 "under that and that circumstances this implementation raises a blurb signal" 但它不能说 "under that and that circumstances we don't tell you what we are doing".
不要把未定义的行为神秘化为会发生的事情,甚至是可以定义的事情。
将整数分配给更小的类型有点奇怪,因为标准清楚地认识到某些实现可能会陷入困境,但是——独特地——它要求陷阱遵守信号规则;在这里而不是其他地方强加这一要求的决定有点奇怪,因为在许多情况下,它会阻碍原本直接的优化——替换类型短于 int
且地址永远不会为已拍摄,带有 int
.
尽管如此,无论出于何种原因,该标准的作者都竭尽全力禁止这种优化。 [注意:如果我负责标准,我会指定显式 cast 到较短的整数类型将产生一个值,当转换为相同大小的无符号类型时只要存在这样的值,就会产生与直接转换该值相同的结果,但是将超大值直接存储到左值 而无需转换 不会因此受到限制;不过标准不是我写的。
这很讽刺,实际上:给定:
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
,但有一些无符号的编译器可以做任何它想做的事情,包括回到过去并假装没有实现会承诺总是以与模块化算术一致的方式执行半尺寸无符号乘法。
3.4.1
1 implementation-defined behavior
unspecified behavior where each implementation documents how the choice is made
在可能出现未定义行为的情况下,实现是否可以指定实现定义的行为是未定义行为?
例如:
6.3.1.3 Signed and unsigned integers
3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.
因此,只要记录在案,该结果是否会被实现未定义并导致未定义的行为,或者它必须具有该实现的已定义结果?
根据 C11
标准,第 3.4.1 章,
implementation-defined behavior
unspecified behavior where each implementation documents how the choice is made
因此,每个实现都必须做出选择。否则,它不会符合。因此,我们可以说,它 必须 具有针对该实现的定义结果。可以是以下任何一种
- 一个定义的行为,特定于该实现,如果遇到指令,将执行该行为。
- a defined 信号,如果遇到指令,将发出信号。 (多半是说处理不了。)
相关:
- 来自
C99
Rationale Document,第 3 章,(强调我的)
Implementation-defined behavior gives an implementor the freedom to choose the appropriate approach, but requires that this choice be explained to the user. Behaviors designated as implementation-defined are generally those in which a user could make meaningful coding decisions based on the implementation’s definition. Implementors should bear in mind this criterion when deciding how extensive an implementation definition ought to be. As with unspecified behavior, simply failing to translate the source containing the implementation defined behavior is not an adequate response.
现在,没有人可以根据未定义的行为做出“有意义的编码决策”。
- 来自 C FAQ,问题 11.33,
implementation-defined: The implementation must pick some behavior; it may not fail to compile the program. (The program using the construct is not incorrect.) The choice must be documented. The Standard may specify a set of allowable behaviors from which to choose, or it may impose no particular requirements.
第一句是必须,和我之前回答的一样
您可以在 C 基本原理 中找到 "implementation defined" 的更详细解释 - 而不是标准文档 本身 ,但很好的参考。
在第 1.6 章中 Definition of terms:
Implementation-defined behavior gives an implementor the freedom to choose the appropriate approach, but requires that this choice be explained to the user. Behaviors designated as implementation-defined are generally those in which a user could make meaningful coding decisions based on the implementation definition. Implementors should bear in mind this criterion when deciding how extensive an implementation definition ought to be. As with unspecified behavior, simply failing to translate the source containing the implementation-defined behavior is not an adequate response.
你不能"reasonable coding decision"基于未定义的行为。
C 常见问题解答(同样,不是标准,而是众所周知的参考)是 quite clear too:
implementation-defined: The implementation must pick some behavior; it may not fail to compile the program. (The program using the construct is not incorrect.) The choice must be documented. The Standard may specify a set of allowable behaviors from which to choose, or it may impose no particular requirements
未指定和实现定义的行为都不是错误 - 编译器不会使翻译失败。它们旨在提供实现选项,以便为目标环境生成最佳代码。
不,从语义上讲这是不可能的。未定义的行为是术语所述,标准未定义的行为。如果标准要求实现定义的行为,它会明确要求实现指定发生特定错误时要执行的操作。
undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
所以一个实现可以说 "under that and that circumstances this implementation raises a blurb signal" 但它不能说 "under that and that circumstances we don't tell you what we are doing".
不要把未定义的行为神秘化为会发生的事情,甚至是可以定义的事情。
将整数分配给更小的类型有点奇怪,因为标准清楚地认识到某些实现可能会陷入困境,但是——独特地——它要求陷阱遵守信号规则;在这里而不是其他地方强加这一要求的决定有点奇怪,因为在许多情况下,它会阻碍原本直接的优化——替换类型短于 int
且地址永远不会为已拍摄,带有 int
.
尽管如此,无论出于何种原因,该标准的作者都竭尽全力禁止这种优化。 [注意:如果我负责标准,我会指定显式 cast 到较短的整数类型将产生一个值,当转换为相同大小的无符号类型时只要存在这样的值,就会产生与直接转换该值相同的结果,但是将超大值直接存储到左值 而无需转换 不会因此受到限制;不过标准不是我写的。
这很讽刺,实际上:给定:
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
,但有一些无符号的编译器可以做任何它想做的事情,包括回到过去并假装没有实现会承诺总是以与模块化算术一致的方式执行半尺寸无符号乘法。