C中的无符号int的行为为负
我不明白为什么对于下面的代码,无符号int的输出是负数。 就像一个带符号的intC中的无符号int的行为为负,c,printf,undefined-behavior,C,Printf,Undefined Behavior,我不明白为什么对于下面的代码,无符号int的输出是负数。 就像一个带符号的int uint32_t yyy=1<<31; printf("%d\n",yyy); uint32\u t yyy=1这是因为printf参数%d隐式地将数字转换为整数 改用%u。使用%u输出无符号数字: printf("%u\n", yyy); 您需要使用无符号int格式说明符: printf("%u\n",yyy); ^^ 为printf使用错误的格式说明符是未定义的行为,C
uint32_t yyy=1<<31;
printf("%d\n",yyy);
uint32\u t yyy=1这是因为printf参数%d隐式地将数字转换为整数
改用%u。使用%u
输出无符号数字:
printf("%u\n", yyy);
您需要使用无符号int
格式说明符:
printf("%u\n",yyy);
^^
为printf
使用错误的格式说明符是未定义的行为,C99标准草案部分7.19.6.1
涵盖了这一点。fprintf函数也涵盖了格式说明符方面的printf
:
如果转换规范无效,则行为无效
未定义。248)如果任何参数的类型不正确
对应的转换规范,行为未定义
printf
的页面有一个很好的表格,指定可用的格式说明符。%d
的格式说明符要求的是int
,而不是无符号int
,因此代码具有未定义的行为。根据C99标准第7.19.6.1节的fprintf功能:
如果任何参数不是相应转换规范的正确类型,则行为未定义
对无符号整数使用%u
:
uint32_t yyy=1u<<31;
printf("%u\n",yyy);
uint32\u t yyy=1u因为您正在将其作为签名打印。使用%u
。正如许多人所说,使用%u
标识符
原因是,printf
无法判断任何额外参数的类型(它们作为va_列表
给出),因此程序员必须使用格式字符串提供该信息。然后,当您提供%d
时,printf
将调用:
int val;
val = va_arg(va_list, int);
并隐式地将unsigned int转换为signed。printf
接受数量可变的参数。当您调用它时,编译器会尽职尽责地将它们全部放在堆栈上。因为它是C,所以没有反射-printf
无法推断它收到的东西的类型。在位级别上,您无法初步区分有符号整数、无符号整数或浮点、适当小的结构、较大结构的一部分等
这就是为什么还必须提供格式字符串。它告诉printf
从堆栈中读取的类型以及顺序。它完全依赖于该格式字符串,无法验证它
因此,根据已经发布的单行答案,如果您告诉它将字段解释为有符号的数量,那么它将被打印为有符号的数量。整数以格式存储。这意味着仅仅通过查看值无法判断数字是有符号的还是无符号的。您必须告诉机器您希望它使用的表示形式,并自己跟踪它
在您的示例中,您告诉机器,jjj
未签名(用于类型检查),然后要求printf()
将其视为已签名,方法是在格式字符串中使用%d
(无法获取类型信息)。如果要打印未签名的int,请改用%u
。尝试printf(“%u\n”,yyy)
即使在调用printf
之前,如果int
在您的C实现中有32位,则此代码具有未定义的行为。1I的值见。感谢您的回答~出于可移植性考虑,您可以使用以下内容打印uint32_t(可能比未签名的更大):'printf(“%”PRIu32“\n”,yyy);'
int val;
val = va_arg(va_list, int);