该标准要求实现以某种方式记录当整数转换为太小而无法容纳它的有符号类型时,它们将如何确定使用什么值。它没有具体说明此类文件将采用的形式。符合标准的实现的文档可以在可读的打印中指定值将被截断并扩展二进制补码符号,然后在不可能的小字体中指定“......除非在一个月的第五个星期二编译程序,在这种情况下范围转换将产生值 24601"。当然,这样的文档不会有帮助,但标准本身并不关心“实施质量”问题。
在实践中,以除 100% 一致截断和补码符号扩展之外的任何方式定义行为的实现极为罕见。如果事实上 100% 的符合 C99 和 C11 的用于生产代码的实现默认以这种方式工作,我不会感到特别惊讶。不幸的是,无论是<limits.h>
或任何其他标准头文件都没有定义任何实现可以表明它们遵循基本通用约定的方法。
可以肯定的是,期望通用行为的代码不太可能被任何符合标准的编译器的行为所绊倒。然而,编译器可能会提供一种不一致的模式是合理的,因为这可以使某些类型的代码更有效率。例如,给定:
int32_t x,i;
int16_t *p;
...
x = ++p[i];
如果int
大于 16 位,则行为将在p[i]
代码执行之前定义为 32767 的情况。增量将产生 -32768,该值将以int16_t
实现定义的方式转换为(保证产生 -32768,除非实现记录其他内容),然后该值将存储到x
和p[i]
。
在像 ARM 这样总是使用 32 位进行算术运算的处理器上,截断存储的值p[i]
不会花费任何成本,但截断写入的值x
需要一条指令(或者,对于某些较旧的 ARM 型号,需要两条指令)。在这种情况下允许x
接收 +32768 将提高此类处理器的效率。这样的选项不会影响大多数程序的行为,但如果标准定义了一种方法,依赖于行为的代码可以通过该方法说,例如
#ifdef __STDC_UNUSUAL_INT_TRUNCATION
#error This code relies upon truncating integer type conversions
#endif
以便那些将受到影响的程序可以防止在这种模式下意外编译。到目前为止,标准还没有定义任何这样的测试宏。