【问题标题】:Unsigned integer into little endian form [duplicate]无符号整数转换为小端形式[重复]
【发布时间】:2012-11-30 20:21:35
【问题描述】:

可能重复:
convert big endian to little endian in C [without using provided func]

我在这一部分遇到了麻烦:如果我想取一个 32 位数字,并且我想将它的字节(1 字节 = 8 位)从大端格式转换为小端格式。例如:

假设我有数字 1。

在 32 位中是这样的:

1st byte 2nd byte 3rd byte 4th byte
00000000 00000000 00000000 00000001

我想要它看起来像这样:

4th byte 3rd byte 2nd byte 1st byte 
00000001 00000000 00000000 00000000 

使具有最低有效值的字节首先出现。我在想你可以使用 for 循环,但我不确定如何在 C++ 中移动位/字节。例如,如果用户输入 1 并且我必须像上面的示例一样将其移位,我不确定如何将 1 转换为位,然后移位。谁能指出我正确的方向?谢谢!

【问题讨论】:

  • @NPE 如果不是同一种语言,怎么可能是重复的?
  • 因为大多数(如果不是全部)关于数字及其运算的规则都从 C 继承到 C++?
  • @LuchianGrigore:当然,但在我看来它仍然是重复的,因为它明确地是关于“移位位和字节”,而不是关于“我如何以花哨的 C++ 风格做到这一点”。当然,社区可以做出其他决定。
  • @NPE imo 这里最优雅的解决方案没有任何位移。
  • @cHao 的想法是 C++ 中有更多的规则和选项。你会关闭一个关于标记为 C++ 的动态大小数组的问题,它是一个暗示后续 mallocs 的 C 问题的欺骗吗? 没有。您建议使用std::vector,即使适用相同的数字和运算规则。

标签: c++ 32-bit bit-shift


【解决方案1】:

<<>> 是 C 和大多数其他 C 风格语言中的按位移位运算符。

做你想做的事情的一种方法是:

int value = 1;
uint x = (uint)value;
int valueShifted = 
    ( x << 24) |                // Move 4th byte to 1st
    ((x << 8) & 0x00ff0000) |  // Move 2nd byte to 3rd
    ((x >> 8) & 0x0000ff00) |  // Move 3rd byte to 2nd
    ( x >> 24);                 // Move 4th byte to 1st

【讨论】:

  • 我最初删除了我的答案,因为我认为这是正确的,但是对于 value 的大值,这会出现 UB。
  • 我认为这对于否定来说是失败的。
  • 可以因否定而失败,是的。从技术上讲,左移一个负数会调用 UB,而右移它会在大多数系统上移动 1 秒。如果 int 是无符号的,也许...
  • 你说得对,我固定使用无符号中间变量,所以应该使用逻辑移位。
  • @LuchianGrigore 虽然与char[] 的联合是UB,但对变量地址的char * 的简单转换不是,所以你可以这样交换它。
【解决方案2】:
uint32_t n = 0x00000001;
std::reverse( (char*)&n, (char*)(&n + 1) );
assert( n == 0x01000000 );

【讨论】:

  • 当字符大小不是 8 位时会变得很奇怪。例如,如果 int 和 chars 都是 32 位,则反转什么都不做。
  • @cHao the C++ Standard guarantees that 1 == sizeof(char) 在问题中我们有一个 32 位 unsigned int 类型,那么如何使用例如 7 位字符来模拟它?
  • sizeof(char) == 1 只承诺一个 char 是一个字节;它对那个字节的大小没有任何承诺。该标准要求每个字节至少 8 位,但允许更多。已经存在(并且在特殊情况下仍然存在)具有 8、9、16、32、36 甚至 64 位字节的系统。在我的 32 位示例中,sizeof(int) == 1。一个字节,就没有什么可交换的了。
  • @cHao 我使用来自stdint.huint32_t,在该标头存在的地方,我们应该有uint8_tint8_t,因为该系统应该支持8 位值。并且保证char是最小整数类型,char应该是8位!
  • &lt;climits&gt; 中有一个 CHAR_BIT 宏是有原因的。也就是说,char 并不总是 8 位宽。至于uint8_t,它只是一个typedef,而且是半可选的;如果一个系统没有这样一个精确的 8 位类型,则不需要提供 typedef。因此,如果您想保证 8 位字符,如果它们是任何其他大小,编译会失败,然后使用uint8_t。但是不要对char 的宽度做任何假设,除非它是一个字节(不是 8 位!)。
【解决方案3】:

使用&lt;&lt;&gt;&gt; 运算符完成移位。与按位 AND (&amp;) 和 OR (|) 运算符一起,您可以做您想做的事:

 int value = 1;
 int shifted = value << 24 | (value & 0x0000ff00) << 8 | (value & 0x00ff0000) >> 8 | (value & 0xff000000) >> 24;

【讨论】:

  • 我认为这是 value 的大值的 UB。
  • §5.8/2 E1 &lt;&lt; E2的值是E1左移E2位位置;空出的位用零填充。 ...如果 E1 具有带符号类型和非负值,并且 E1×2E2 在结果类型中可表示...;否则,行为未定义。
猜你喜欢
  • 2020-04-01
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 2020-04-07
  • 1970-01-01
  • 1970-01-01
  • 2016-03-16
相关资源
最近更新 更多