【问题标题】:using shift-right , something is wrong [duplicate]使用 shift-right ,出了点问题[重复]
【发布时间】:2016-04-25 00:39:54
【问题描述】:

我定义了一个名为 queryData 的结构,如下面的代码。当我尝试使用 shift 和 right 操作来操作和分配一个数据 qdata.data.data4[0] 时,将数据打印出来,我之前所说的数据是 a char 有问题这是 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

【问题讨论】:

  • 右移有符号值是实现定义的。并且左移可以调用未定义的行为。使用无符号固定宽度类型!
  • 哦,还有不要发布链接或文字图片
  • Signed right shift = strange result?。不要使用像 4294967295 这样的幻数,而是使用 0xFFFFFFFF~0u

标签: c


【解决方案1】:

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

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

【讨论】:

  • 知道了。谢谢~
【解决方案2】:

诸如 printf 之类的 Vararg 函数会将所有小于 int 的整数提升为 int。由于 char 是一个整数(在您的情况下为 8 位有符号整数),因此您的 chars 正在通过符号扩展提升为 int。

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

为避免此类提升,您必须在 printf 中使用长度说明符:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-12-23
    • 2022-12-01
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    • 2016-01-01
    • 2011-11-04
    • 1970-01-01
    相关资源
    最近更新 更多