C/C++将signed char打包成int

Any*_*orn 4 c c++ signed byte packing

我需要将四个带符号的字节打包成32位整数类型.这就是我的目标:

int32_t byte(int8_t c) { return (unsigned char)c; }

int pack(char c0, char c1, ...) {
  return byte(c0) | byte(c1) << 8 | ...;
}
Run Code Online (Sandbox Code Playgroud)

这是一个很好的解决方案?它是便携式的(不是通信意义上的)吗?是否有现成的解决方案,或许可以提升?

问题我最关心的是将负位从char转换为int时的位顺序.我不知道应该是什么样的正确行为.

谢谢

Joe*_*ams 7

char不保证签名或未签名(在PowerPC Linux上,char默认为unsigned).传播这个词!

你想要的是像这样的宏:

#include <stdint.h> /* Needed for uint32_t and uint8_t */

#define PACK(c0, c1, c2, c3) \
    (((uint32_t)(uint8_t)(c0) << 24) | \
    ((uint32_t)(uint8_t)(c1) << 16) | \
    ((uint32_t)(uint8_t)(c2) << 8) | \
    ((uint32_t)(uint8_t)(c3)))
Run Code Online (Sandbox Code Playgroud)

这很难看,主要是因为它与C的操作顺序不相符.此外,反斜杠返回是有的,所以这个宏不必是一个大的长行.

另外,我们在转换为uint32_t之前转换为uint8_t的原因是为了防止不必要的符号扩展.


Gra*_*ers 7

我喜欢Joey Adam的答案,除了它是用宏编写的(在许多情况下会导致真正的痛苦),如果'char'不是1字节宽,编译器就不会给你一个警告.这是我的解决方案(基于Joey的).

inline uint32_t PACK(uint8_t c0, uint8_t c1, uint8_t c2, uint8_t c3) {
    return (c0 << 24) | (c1 << 16) | (c2 << 8) | c3;
}

inline uint32_t PACK(sint8_t c0, sint8_t c1, sint8_t c2, sint8_t c3) {
    return PACK((uint8_t)c0, (uint8_t)c1, (uint8_t)c2, (uint8_t)c3);
}
Run Code Online (Sandbox Code Playgroud)

我已经省略了将c0-> c3转换为uint32_t,因为编译器在转换时应该为你处理这个问题,并且我使用c风格的转换,因为它们适用于c或c ++(OP标记为两者).

  • 在C和C++中,`char` _always_的大小为一个字节.字节_may_不是8位. (5认同)