使用shift-right,出了点问题

时间:2016-04-24 16:09:08

标签: c

我定义了一个名为queryData的结构,如下面的代码所示。当我尝试使用shift和right操作来操作和分配数据时,qdata.data.data4 [0],打印出数据,我之前说过的数据是一个字符是错误的。这是8位,但当我打印时,它实际上是32位, 0xffffff8b 。我想知道它是怎么样的。谢谢。

int main(void){
    union Data{
        char data2[2];
        char data4[4];
    };
    struct queryData{
        char byte; // 2bytes or 4bytes.
        union Data data;
    };
    struct queryData qdata;
    unsigned long int data;
    data = rand()%4294967295;
    qdata.byte = 4;
    qdata.data.data4[0] = (char)(data>>24);
    qdata.data.data4[1] = (char)((data<<8)>>24);
    qdata.data.data4[2] = (char)((data<<16)>>24);
    qdata.data.data4[3] = (char)((data<<24)>>24);
    printf("%ld\n",data);
    printf("%x\n",qdata.data.data4[0]);
    printf("%x\n",qdata.data.data4[1]);
    printf("%x\n",qdata.data.data4[2]);
    printf("%x\n",qdata.data.data4[3]);
    printf("%x",(unsigned int)(1804289383<<8)>>24); 
    return EXIT_SUCCESS;
}

结果如下: The result after run

2 个答案:

答案 0 :(得分:1)

您使用的是错误的printf格式。使用%hhd作为char作为数值。如果您希望以十六进制格式打印,则必须使用unsigned char作为类型,而不是char

您所观察到的是,char被提升为int,并将其传递给printf。然后,您将int打印为unsigned十六进制。因为您的平台似乎有一个带符号的char类型并且使用了两个补码来表示负值,所以您会看到所有起始位都已打开的模式。

答案 1 :(得分:0)

诸如printf之类的Vararg函数会将小于int的所有整数提升为int。由于char是一个整数(在你的例子中是8位有符号整数),你的字符将通过符号扩展名提升为int。

由于8b具有前导1位(并且作为8位整数为负),因此它们将被符号扩展,而样本中的其他符号则不会。

要避免此类促销,您必须在printf中使用长度说明符:

printf("%hhx\n",qdata.data.data4[1]);