我想知道为什么printf语句在下面的代码中将字符值显示为4字节值(fffffffe)。由于字符是1字节,所以我认为我们应该只得到FE一个字节值的结果。打印反转字符
int main(void)
{
unsigned char a4=1;
char b4=1;
printf("inverted a4 = %x\t b4= %x\n",~a4, ~b4);
return(0);
}
我想知道为什么printf语句在下面的代码中将字符值显示为4字节值(fffffffe)。由于字符是1字节,所以我认为我们应该只得到FE一个字节值的结果。打印反转字符
int main(void)
{
unsigned char a4=1;
char b4=1;
printf("inverted a4 = %x\t b4= %x\n",~a4, ~b4);
return(0);
}
当你做任何算术或位操作上char
量,它被悄悄地转换为int
第一。这被称为integer promotion。它也会影响short
(和signed char
,unsigned char
和unsigned short
)。 (从技术上讲,如果sizeof(unsigned short) == sizeof(unsigned int)
然后unsigned short
将促进unsigned int
而非int
,但你可能不会在与特性的系统跳闸了,尽管它仍然C标准允许的。)
这也发生在char
和short
当它们通过匿名参数传递到printf
(或任何其他可变参数函数)。
所以,你的代码
unsigned char a4=1;
char b4=1;
printf("inverted a4 = %x\t b4= %x\n",~a4, ~b4);
相当于
...
printf("inverted a4 = %x\t b4= %x\n", (int) ~(int)a4, (int) ~(int)b4);
(该在~
投后没有做任何事情,但我已经写它无论如何强调的是,转换可能发生两,因为算术和因为参数传递。)
有没有办法来打开这种行为关闭。为了得到你想要的效果,我会写
static_assert(CHAR_BIT == 8);
printf("inverted a4 = %02x\tb4 = %02x\n",
(~(unsigned int)a4) & 0xFFu,
(~(unsigned int)b4) & 0xFFu);
这和MikeCAT和尼克建议的代码之间的区别是,所有的位操作上无符号量完成。有些操作在应用于带符号数量时具有未定义的行为,并且我无法准确记住规则是什么,所以我只是避免将它们中的任何一个用于有符号数量。 (从%x
到%02x
的变化仅仅是为了美观。)
static_assert
失败的系统现在很少见,但仍然被C标准允许。我主要把它包括在内以记录程序的期望。 (该0xFFu
掩模和%02x
格式化是错具有用于CHAR_BIT
不同的值的系统。)
sizeof(~b4)
为4中Wandbox。
要得到只有FE,使用AND掩码。
此外,将%x
更改为%X
以获得FE,而不是fe。
#include <stdio.h>
int main(void)
{
unsigned char a4=1;
char b4=1;
printf("inverted a4 = %X\t b4= %X\n",(~a4) & 0xFF, (~b4) & 0xFF);
return(0);
}
参数%X和%x预计为int
。
您提供char
,它被铸造为int
。
的解决方案是为MikeCAT给:
printf("inverted a4 = %X\t b4= %X\n",(~a4) & 0xFF, (~b4) & 0xFF);
这样做的原因是这样的......(省略号)函数C.工作当char参数提供给省略的功能,它是“扩大'int(或unsigned int,取决于char是有符号还是无符号)。实际上,小于int的所有东西都被扩展(正确的术语被提升)为int。作为这次升级的结果,当printf看到这个价值时,它已经被提升了。顺便提一下,float以同样的方式被提升为double。
编译器在将字符反转之前将字符(0x01
)提升为32位整数(0x00000001
),这会给出值(0xFFFFFFFE
)。
你可以做一个位与作为其他的答案中提到,或添加一个类型转换的答案转换回char
类型之后:
unsigned char a4=1;
char b4=1;
printf("inverted a4 = %X\t b4= %X\n",(unsigned char)(~a4), (char)(~b4));
return(0);
'(char)' - >'(unsigned char)' – BLUEPIXY
它不给出'0xFFFFFFFE'的值;它给出值'-2'。 –
的~
操作者的操作经历整数促销 。 char
或unsigned char
类型的操作数被提升为int
,结果为int
。
char b4=1;
b4
是char
类型。
~b4
的b4
值晋升为int
,并且操作者~
产生的1
按位求补。如果int
是32位,则结果是-2
,假设有符号整数的2的补码表示。
printf"%x\n", ~b4);
的int
值-2
被打印,好像它是unsigned char
类型;结果是fffffffe
。
如果你只想低8位,你可以使用一个位掩码:
printf("%X\n", ~b4 & 0xFF);
这将打印FE
。
打印用'hh'如在'的printf( “倒A4 =%HHX \吨B4 =%HHX \ n” 个,〜 a4,〜b4);'以避免打印符号扩展名。 – chux