打印字符的反转

时间:2015-09-30 15:39:53

标签: c

我想知道为什么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);
}

6 个答案:

答案 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 charunsigned charunsigned short)。 (从技术上讲,如果sizeof(unsigned short) == sizeof(unsigned int)然后unsigned short会升级为unsigned int而不是int,但您不太可能会跳过具有该特征的系统,即使它是仍然允许C标准。)

charshort通过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);