原始数据类型的值超出范围和C99的PRI*宏的行为

Ykt*_*ula 3 c

假设我们有一个8位无符号整数n(UINT8_MAX=255); 编译器的行为是n=256什么?当数据类型的值超出不同数据类型的范围时,我在哪里可以找到默认行为表?超出范围时,它们的行为方式是否存在?

#include <stdio.h>
#include <inttypes.h>

uint8_t n = UINT8_MAX;
int main() {
  printf("%hhu ",n++);
  printf("%hhu",n);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译gcc -std=c99 -Wall *.c,打印:255 0

另外,使用C99的PRI*宏是否可以接受?他们是如何命名的?

Ste*_*sop 5

n=256;将有符号整数值转换256uint8_t,然后将其赋值给n.此转换由标准定义,取值为modulo-256,因此结果n是设置为0.

不确定在哪里可以找到表,但整数转换的规则是6.3.1.3:

1当具有整数类型的值转换为除_Bool之外的另一个整数类型时,如果该值可以由新类型表示,则它将保持不变.

2否则,如果新类型是无符号的,则通过重复加或减一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内.49)

3否则,新类型已签名且值无法在其中表示; 结果是实现定义的,或者引发实现定义的信号

正如AndreyT指出的那样,这并未涵盖在计算过程中出现超出范围值时发生的情况,而不是转换期间发生的情况.对于6.2.5/9涵盖的无符号类型:

涉及无符号操作数的计算永远不会溢出,因为无法通过生成的无符号整数类型表示的结果将以比结果类型可以表示的最大值大1的数量为模.

对于签名类型,3.4.3/3说:

示例未定义行为的示例是整数溢出的行为.

(间接,我知道,但是当这是未定义行为的规范示例时,我懒得继续搜索显式描述).

另请注意,在C中,整数提升规则非常棘手.算术运算总是在相同类型的操作数上执行,因此如果表达式涉及不同的类型,则有一个规则列表来决定如何选择要执行操作的类型.两个操作数都被提升为此公共类型.但它始终至少是一个int,所以对于类似的小类uint8_t,算术将在a中完成int并转换回uint8_t赋值给结果.例如:

uint8_t x = 100;
uint8_t y = 100;
unsigned int z = x * y;
Run Code Online (Sandbox Code Playgroud)

结果是10000,而不是16,如果z也是uint8_t如此.

另外,使用C99的PRI*宏是否可以接受?他们是如何命名的?

可以接受谁?我不介意,但您可能想检查您的编译器是否支持它们.海湾合作委员会在我最早的版本中做了,3.4.4.它们在7.8.1中定义.

如果您没有C标准的副本,请使用:http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf.这是该标准的"草案",在标准发布后的某个时间发布,包括一些更正.