【问题标题】:small bitoperation problem with unsigned int in combination with unsigned charunsigned int 结合 unsigned char 的小位操作问题
【发布时间】:2020-02-21 22:51:20
【问题描述】:

您好,我遇到了一个关于位操作的小概念问题。 请参阅下面的代码,其中我有一个 4 字节的无符号整数。然后我通过将地址分配给无符号字符来访问各个字节。

然后我将最后一个字节的值设置为 1。并对无符号整数(4byte 变量)执行右移。我不明白为什么这个操作明显改变了 3byte 的内容。

查看下面的代码以及运行时的输出

#include <cstdio>

int main(int argc,char **argv){
  fprintf(stderr,"sizeof(unsigned int): %lu sizeof(unsigned char):%lu\n",sizeof(unsigned int),sizeof(unsigned char));
  unsigned int val=0;
  unsigned char *valc =(unsigned char*) &val;
  valc[3] = 1;
  fprintf(stderr,"uint: %u, uchars: %u %u %u %u\n",val,valc[0],valc[1],valc[2],valc[3]);
  val = val >>1;
  fprintf(stderr,"uint: %u, uchars: %u %u %u %u\n",val,valc[0],valc[1],valc[2],valc[3]);
  return 0;
}


sizeof(unsigned int): 4 sizeof(unsigned char):1
uint: 16777216, uchars: 0 0 0 1
uint: 8388608, uchars: 0 0 128 0

提前致谢

【问题讨论】:

  • 您的第一个线索将是对第一个数字出现为“16777216”的原因进行自夸。然后尝试将其他三个字节设置为1,一次一个,看看结果如何,你应该可以自己找出原因。
  • 请注意,correct format specifier for size_t(这是sizeof() 返回的内容)是"%zu",而不是"%lu"。使用不正确的格式说明符会调用未定义的行为。

标签: c bit-manipulation bit


【解决方案1】:

您发现您的计算机并不总是按照您期望的顺序存储多字节数据类型的字节。 valc[0] 是系统上的最低有效字节 (LSB)。由于 LSB 存储在最低内存地址,因此被称为“小端”系统。在另一端,valc[3] 是最高有效字节 (MSB)。

如果您改为打印 valc[3],valc[2],valc[1],valc[0],您的输出对您来说会更有意义,因为人们期望最重要的值在左侧。

其他计算机体系结构是“大端”,将首先存储最高有效字节。

这篇文章还更详细地解释了这个概念: https://en.wikipedia.org/wiki/Endianness

Brian Kernighan 和 Rob Pike 所著的“编程实践”一书也包含一些关于字节顺序(第 8.6 节字节顺序)以及如何编写可在大端和小端系统上工作的可移植程序的良好内容。

【讨论】:

    【解决方案2】:

    如果我们将 int 的输出更改为十六进制(即将 %u 更改为 %x),会发生什么变得更加明显:

    uint: 1000000, uchars: 0 0 0 1
    uint: 800000, uchars: 0 0 128 0
    

    val右移 1。这导致最高位字节的低位移到下一个字节的高位。

    【讨论】:

    • 好吧,也许我的误解是 shiftright 实际上并不意味着该位实际上是向右移动,而是向最低有效位方向移动?
    • 是的,当您向右移动时,所有内容都向最低有效位移动。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 2012-01-27
    相关资源
    最近更新 更多