对char的按位运算给出32位结果

时间:2012-06-12 17:35:48

标签: c char bitwise-operators

我一直在用C编写程序,将char的前4位移到最后,最后4位移动到开头。对于大多数值,它正常工作,以及反向操作,但对于某些值,如8,x,y,z,它给出32位值的结果。通过打印变量的十六进制值来检查值。任何人都可以解释为什么会这样吗?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char o, f,a=15;
    scanf("%c",&o);
    printf("o= %d\n",o);
    f=o&a;
    o=o>>4;
    printf("o= %d",o);
    o=o|(f<<4);
    printf("o= %x, size=%d\n",o,sizeof(o));
    f=o&a;
    o=o>>4;
    printf("o= %d",o);
    o=o|(f<<4);
    printf("o= %x, size=%d\n",o,sizeof(o));
    return 0;
}

4 个答案:

答案 0 :(得分:6)

o作为参数传递给printf()会导致自动转换为int,这显然是系统上的32位。自动转换使用符号扩展,因此如果设置了o中的第7位,则将设置转换结果中的位8-31,这将解释您所看到的内容。

您可以使用unsigned char代替char来避免这种情况。或者将o & 0xff传递给printf()

答案 1 :(得分:3)

尝试将变量声明为unsigned char。你正在获得高位的符号扩展。

答案 2 :(得分:2)

作为printf(或任何可变函数,或任何没有原型的函数)的参数提供的char被提升为int。如果在您的平台上签署了char并且传递的值为负,则会延长该符号。

答案 3 :(得分:2)

您的值将打印为32位值,因为格式说明符%x告诉printf将值打印为unsigned int。要将其打印为unsigned char,您需要格式说明符%hhxhh长度修饰符。如果值为正,则对打印输出没有影响,但对于负数,它会因为它们具有最高有效位而设置。

对于以下内容,解释在该代码中如何出现负值,我假设CHAR_BIT == 8和二进制补码表示负整数。

对于班次,o的值会提升为int。如果设置了原始值的第四个最低有效位(如果(o & 8) != 0),则在第一次交换半字节之后,设置o的最高有效位。如果您的平台默认使用char,则表示结果为否定。对于第二个半字节交换,o的值再次提升为int,从而产生负值。负值的右移是实现定义的,所以

o=o>>4;
在这种情况下,

不可移植(尽管实际上所有实现都使用算术右移[带符号扩展]或逻辑右移[从左移零]。

在对负整数进行算术移位的实现中,o的四个最高有效位都将被设置,所以

o=o|(f<<4);

不再更改该值。

可移植修复代码以获得所需行为的唯一方法是将o声明为Ned建议的unsigned char。然后所有的数值都是正数,并且变化的行为是明确的,并符合您的期望。