我在Windows 7上的Code :: Blocks 10.05中编译了以下C程序。
int main()
{
unsigned char a=-5;
signed char b=-5;
char c=-5;
printf("%d %d %d \n",a,b,c);
printf("%u %u %u \n",a,b,c);
}
我期待以下输出
251 -5 -5
251 251 251
我的理由是这样的,
-5在2的补语表示中表示为1111 1011。 因此将打印251。
但我得到了以下输出。
251 -5 -5
251 4294967291 4294967291
我知道4294967291是-5位的32位2的补码表示。
但为什么unsigned char a打印为251而不是4294967291?
答案 0 :(得分:4)
printf
是一个可变函数,它导致(感谢@TheParamagneticCroissant进行校正)将整数参数提升为int或unsigned int。根据标准促销规则将签署适当的扩展。这导致您获得的数字是此促销过程后的结果。
相反,您可以使用"%" PRIu8
打印8位无符号和"%" PRId8
来打印8位有符号数。但请注意,参数仍将被提升,然后printf将根据格式说明符再次向下转换它们,这可能仍然会改变该值,但我不确定它是否来自内存。
此外,C不能保证char为8位,最好包含<stdint.h>
标头并使用正确的固定宽度类型。
您的代码的固定版本如下:
#include <stdint.h>
int main()
{
uint8_t a=-5;
int8_t b=-5;
printf("%" PRId8 "%" PRId8 "\n", a, b);
printf("%" PRIu8 "%" PRIu8 "\n", a, b);
}
注意我没有包含等效的char,因为所有固定宽度类型都是已定义的符号,因此没有直接等效的char,它具有未定义的签名。
答案 1 :(得分:2)
unsigned
整数类型(包括unsigned char
)使用模运算。对于unsigned char
,它是模UCHAR_MAX + 1
,其中UCHAR_MAX
是<limits.h>
中实现定义的值,具有典型值,大多数实现为255
({{ 1}}也是标准允许255
)的最小值。将UCHAR_MAX
添加到256
(即在-5
和0
之间获得余数以便在代码中初始化255
)将解释为什么{{1} }的值为a
。
至于为什么任何值都在打印时,这些值在传递给a
时会被提升为251
类型。此促销与您的格式字符串无关,但是int
格式说明符所需的内容,因此值将打印出来。
答案 2 :(得分:1)
@Vality的回答有点不对劲。由于unsigned char
必须保存最多至少255的值,因此如果uint8_t存在,CHAR_BIT
必须为8。
没有理由使用讨厌的PRI
宏,只需使用它:
unsigned char a = -5;
signed char b = -5;
char c = -5;
printf("%hhd %hhd %hhd \n", a, b, c);
printf("%hhu %hhu %hhu \n", a, b, c);
答案 3 :(得分:0)
因为a
包含值251
,而不是值-5
。