在C中打印时有符号和无符号字符的行为
我在Windows7上编译了下面的C程序,代码是::Blocks 10.05在C中打印时有符号和无符号字符的行为,c,C,我在Windows7上编译了下面的C程序,代码是::Blocks 10.05 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的补码表示法中表示为1111011。
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的补码表示法中表示为1111011。
因此,将打印251
但我得到了以下输出
251 -5 -5
251 4294967291 4294967291
我知道4294967291是-5的32位2的补码表示
但是为什么无符号字符a被打印为251而不是4294967291?
printf
是一个可变函数,它会导致(由于@TheParamagneticCroissant的更正)积分参数被提升为int或无符号int。根据标准提升规则,它会对它们进行适当的符号扩展。这使得你得到的数字成为这次晋升过程后的结果
相反,您可以使用“%”PRIu8
打印8位无符号数字,使用“%”PRId8
打印8位有符号数字。但是请注意,参数仍将被提升,然后printf将根据格式说明符再次向下转换它们,这可能仍然会更改该值,但我无法从内存中确定这一点
此外,C中的字符不能保证为8位,最好包含
标题并使用适当的固定宽度类型
您的代码的固定版本如下:
#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);
}
#包括
int main()
{
uint8_t a=-5;
int8_t b=-5;
printf(“%”PRId8“%”PRId8“\n”,a,b);
printf(“%“PRIu8”%“PRIu8”\n”,a,b);
}
注:我不包括字符的等价物,因为所有固定宽度类型都是定义的符号,因此没有直接等价于字符的未定义符号。因为
a
持有值251
,而不是值-5
。Vality的回答稍有错误。因为unsigned char
必须至少保存255个值,所以如果uint8\u t存在,char\u 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);
无符号
整数类型(包括无符号字符
)使用模运算。对于unsigned char
,即模UCHAR\u MAX+1
,其中UCHAR\u MAX
是
中实现定义的值,大多数实现为255
(255
也是标准允许的UCHAR\u MAX
的最小值)。将256
添加到-5
(即获得0
和255
之间的余数,以便在代码中初始化a
)将解释a
的值为251
的原因
至于为什么要打印任何值,当传递到
printf()
时,这些值被提升为int
类型。此提升与格式字符串无关,但它是%d
格式说明符所期望的,因此值会按您所看到的方式打印。printf()
是可变的;它的参数被提升为int
,如果它们比int
窄,这是通常算术转换的一部分。请参阅,例如,您必须将格式说明符与类型匹配<代码>%d应用于所有字符类型。(还有其他说明符,但它们是不必要的)<代码>%u只能用于无符号字符
(字符类型之外)。您的%u
行会导致未定义的行为。这与非常类似,但我不确定它是否为重复。这两个问题的结果相似,但措辞却完全不同。如果投票人愿意提及我做错了什么,我将非常感激,因为我很累,身上没有C编译器,所以我只从内存中编码。“使用%u和%d格式说明符打印整数大小的有符号和无符号数字。这意味着您的字符将被提升为int和unsigned int“-否,它们将被提升,而不考虑格式说明符;它们被提升是因为printf()
是可变的。它们也仅被提升为一种特定类型(根据int
和char
的大小和范围,它可以是int
或unsigned int
,在大多数现代机器上可能是int
。)谢谢你修复它;我收回了我的DV。我还建议我们找一个重复的问题,我几乎完全肯定这个问题已经被问过好几次了。@ParamagneticCroissant你能不能看一下修复后的答案,我不想误导OP,即使修复后我也不能100%肯定我是对的。此外,我将我四处看看,看能不能找到一个dupeIm,我不太确定,我相信char可以更大(比如说12位),而uint8_不是另一个没有名字的离散类型。虽然我面前没有标准,所以不能肯定这是否是允许的,是否有任何系统可以做到。但是如果你这样做,我强烈建议你对字符位和错误进行显式检查。我同意你的观点lution可以在所有机器上工作,但最复杂的机器除外。@Vality没有一种类型可以小于char
。但是我真的不在乎那些古老的系统,它们甚至不会有一个半新的libc。