C中的unsigned int表现为负数

我不明白为什么unsigned int的输出对于以下代码是负的。 就像一个签名的int。

uint32_t yyy=1<<31; printf("%d\n",yyy); 

输出是:

-2147483648

这是-2^31

%d的格式说明符需要int ,而不是unsigned int ,因此代码具有未定义的行为。 从C99标准部分7.19.6.1 fprintf函数

如果任何参数不是相应转换规范的正确类型,则行为未定义。

使用%u表示unsigned int

 uint32_t yyy=1u<<31; printf("%u\n",yyy); 

输出:

 2147483648

这是因为你的printf参数,如%d,是隐式地将你的数字转换为int。

请改用%u。

使用%u输出无符号数:

 printf("%u\n", yyy); 

正如许多人所说,使用%u标识符。

原因是printf没有办法告诉任何额外参数是什么类型(它们是作为va_list给出的),因此程序员必须使用格式字符串提供该信息。 当你提供%dprintf会调用:

 int val; val = va_arg(va_list, int); 

并隐式地将unsigned int转换为signed。

因为您将其打印为已签名。 请改用%u

printf采用可变数量的参数。 当你调用它时,编译器将尽职尽责地将它们全部放在堆栈中。 因为它是C,所以没有reflection – printf不能随后推断它收到的东西的类型。 在位级别,您无法表示无符号整数或浮点数的有符号整数,适当的小结构,较大结构的一部分等。

这就是为什么你还必须提供格式字符串。 它告诉printf从堆栈中读取什么类型以及以什么顺序读取。 它完全取决于格式字符串,无法validation它。

因此,根据已发布的单行答案,如果您告诉它将字段解释为签名数量,则它将打印为签名数量。

整数以二进制补码格式存储。 这意味着只能通过查看值来判断数字是已签名还是无符号。 您必须告诉机器您希望它使用哪种表示forms并自行跟踪。

在您的示例中,您告诉计算机jjj是无符号的(用于类型检查),但是请求printf()通过在格式字符串中使用%d将其视为已签名(它无法获取类型信息)。 如果要打印unsigned int,请改用%u

您需要使用unsigned int格式说明符:

 printf("%u\n",yyy); ^^ 

使用错误的printf格式说明符是未定义的行为,这在C99草案标准第7.19.6.1节中7.19.6.1 介绍fprintf函数 ,它还包含关于格式说明符的printf

如果转换规范无效,则行为未定义。 248)如果任何参数不是相应转换规范的正确类型,则行为未定义。

printf的cppreference页面有一个很好的表,指定了可用的格式说明符。