unsigned char和char XOR操作

时间:2016-03-13 17:20:48

标签: c types xor

有没有人可以帮我解释XOR操作中unsigned char和char之间的区别?

#include <stdio.h>

int main() {
    char a[2] = { 0x56, 0xa5 };  // a[0]  0101 0110   
                                 // a[1]  1010 0101 
    a[0] = a[0] ^ a[1];          // a[0]  1111 0011    f3   
    printf("%02x", a[0]);
    puts("");

    unsigned char b[2] = { 0x56, 0xa5 }; // b[0]  0101 0110
                                         // b[1]  1010 0101 
    b[0] = b[0] ^ b[1];                  // b[0]  1111 0011    f3   
    printf("%02x", b[0]);
    puts("");
}

结果:

fffffff3
f3
[Finished in 0.0s]

另一个例子:

#include <stdio.h>

int main() {
    char a[2] = { 0x01, 0x0a };

    a[0] = a[0] ^ a[1];          
    printf("%02x", a[0]);
    puts("");

    unsigned char b[2] = { 0x01, 0x0a };       

    b[0] = b[0] ^ b[1];             
    printf("%02x", b[0]);
    puts("");
}

结果:

0b
0b
[Finished in 0.0s]

2 个答案:

答案 0 :(得分:1)

在第一种情况下,您的代码

printf("%02x", a[0]);

char值传递给可变参数函数printfchar值将提升为int类型并按原样传递。 a[0]的值为-13,因为您的环境默认情况下会对char类型进行签名,该值会被促销保留为int,而printf会将其作为int接收%02x

格式unsigned int需要printf值。 int传递了int值,这是一种调用未定义行为的错误类型。由于unsigned int-13在您的平台上使用相同的参数传递约定,因此unsigned int的负值被解释为具有相同位模式的0xFFFFFFF3,值为{{ 1}}因为平台上的int有32位,负值用2s补码表示。 printf生成的字符串为fffffff3。 C标准实际上并未保证此行为。

在第二个示例中,b[0]unsigned char,其值为2430xf3)。其促销至int会保留价值,而传递给int的{​​{1}}则为printf。调用相同的未定义行为,因为243传递printf而不是int。在您的特定情况下,由unsigned int执行的转化会产生相同的值,该值打印为十六进制,至少2位数字用前导printf填充0

为避免这种歧义,您应该将操作数强制转换为f3

unsigned char

或者将其实际类型指定为printf("%02x", (unsigned)(unsigned char)a[0]);

unsigned char

答案 1 :(得分:0)

(类型char已签名,sizeof(int)为4,每字节8位。)

由于整数提升,a的两个操作数都被提升为int

a[0]^a[1];   

由于a[1]是签名类型char,因此数字0xa5实际上代表负值-91。类型int中-91值的表示形式为0xffffffa5

所以计算结果如下:

0x00000056 ^ 0xffffffa5

或十进制:

86 ^ -91

该操作的结果是:0xfffffff3

此计算的unsigned char版本没有这个问题&#39;。