我想知道为什么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);
}
答案 0 :(得分:2)
background-size: cover;
运算符的操作数经历整数提升。类型~
或char
的操作数将提升为unsigned char
,结果类型为int
。
int
char b4=1;
的类型为b4
。
char
~b4
的值被提升为b4
,而int
运算符会产生~
的按位补码。如果1
是32位,则结果为int
,假设有符号整数的二进制补码表示。
-2
printf"%x\n", ~b4);
值int
的打印方式与-2
类型相同;结果是unsigned char
。
如果只想要低位8位,可以使用按位掩码:
fffffffe
这将打印printf("%X\n", ~b4 & 0xFF);
。
答案 1 :(得分:2)
当您对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和Nick建议的代码之间的区别在于所有位操作都是在 unsigned 数量上完成的。当应用于有符号数量时,某些位操作具有未定义的行为,并且我永远无法确切地记住规则是什么,所以我只是避免将它们中的任何一个用于签名数量。 (从%x
到%02x
的变化仅仅是为了美学。)
static_assert
失败的系统现在非常罕见,但C标准仍然允许这样做。我主要用它来记录程序的期望。 (对于0xFFu
具有不同值的系统,%02x
掩码和CHAR_BIT
格式化程序出错。)
答案 2 :(得分:0)
sizeof(~b4)
在Wandbox中为4。
要获得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);
}
答案 3 :(得分:0)
参数%X和%x需要int
。
您提供char
并将其投放到int
。
解决方案就像MikeCAT一样:
printf("inverted a4 = %X\t b4= %X\n",(~a4) & 0xFF, (~b4) & 0xFF);
答案 4 :(得分:0)
原因是......(省略号)函数在C中工作。当char参数提供给省略号函数时,它被“扩展”为int(或unsigned int,具体取决于char是有符号还是无符号)。实际上,小于int的所有东西都被扩展(正确的术语被提升)到int。作为此促销的结果,当printf看到该值时,它已经被提升。顺便说一句,浮动以同样的方式被提升为双倍。
答案 5 :(得分:0)
编译器在将字符(0x01
)反转之前将其提升为32位整数(0x00000001
),这会得到值(0xFFFFFFFE
)。
您可以按照提到的其他答案执行按位AND,或者添加类型强制转换以将之后的答案转换回char
类型:
unsigned char a4=1;
char b4=1;
printf("inverted a4 = %X\t b4= %X\n",(unsigned char)(~a4), (char)(~b4));
return(0);