我一直在用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;
}
答案 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
,您需要格式说明符%hhx
和hh
长度修饰符。如果值为正,则对打印输出没有影响,但对于负数,它会因为它们具有最高有效位而设置。
对于以下内容,解释在该代码中如何出现负值,我假设CHAR_BIT == 8
和二进制补码表示负整数。
对于班次,o
的值会提升为int
。如果设置了原始值的第四个最低有效位(如果(o & 8) != 0
),则在第一次交换半字节之后,设置o
的最高有效位。如果您的平台默认使用char
,则表示结果为否定。对于第二个半字节交换,o
的值再次提升为int
,从而产生负值。负值的右移是实现定义的,所以
o=o>>4;
在这种情况下,不可移植(尽管实际上所有实现都使用算术右移[带符号扩展]或逻辑右移[从左移零]。
在对负整数进行算术移位的实现中,o
的四个最高有效位都将被设置,所以
o=o|(f<<4);
不再更改该值。
可移植修复代码以获得所需行为的唯一方法是将o
声明为Ned建议的unsigned char
。然后所有的数值都是正数,并且变化的行为是明确的,并符合您的期望。