【问题标题】:How to cast char array to int at non-aligned position?如何在非对齐位置将 char 数组转换为 int?
【发布时间】:2015-01-15 16:34:38
【问题描述】:

在 C/C++ 中有没有办法在任何位置将 char 数组转换为 int?

我尝试了以下方法,如果我尝试使用带有非常量偏移的指针算法,它会自动对齐最近的 32 位(在 32 位架构上):

unsigned char data[8];
data[0] = 0; data[1] = 1; ... data[7] = 7;
int32_t p = 3;
int32_t d1 = *((int*)(data+3));  // = 0x03040506  CORRECT
int32_t d2 = *((int*)(data+p));  // = 0x00010203  WRONG

更新:

  • 如 cmets 中所述,输入以 3 元组的形式出现,我不能 改变它。
  • 我想进一步将 3 个值转换为 int 处理,并且这种转换应该尽可能快。
  • 该 解决方案不必是跨平台的。我正在与一个非常 具体的编译器和处理器,所以可以假设是32 大端位架构。
  • 结果的最低字节对我来说并不重要(见上文)。

我目前的主要问题是:为什么 d1 有正确的值而 d2 没有?这对其他编译器也是如此吗?这种行为可以改变吗?

【问题讨论】:

  • 版主说明:cmets 下放。他们被删除了。如果您有答案,请发布。有更好的方法吗?发布它作为答案!抓住机会。
  • 由于这似乎不可能,我通过一次使用 4 个像素来部分解决它以避免对齐问题。
  • 这也不起作用...编译器似乎在 2^N 边界对齐。

标签: c++ c alignment reinterpret-cast pointer-arithmetic


【解决方案1】:

不,你不能以便携的方式做到这一点。

尝试从 char* 转换为 int* 时遇到的行为在 C 和 C++ 中未定义(可能是因为您发现的原因:ints 可能在 4 字节边界上对齐,data 当然是连续的。)

data+3 有效但 data+p 无效的事实可能是由于编译时间与运行时评估。)

另请注意,char 的签名性在 C 或 C++ 中均未指定,因此如果您正在编写这样的代码,则应使用 signed charunsigned char

最好的办法是使用按位移位运算符(>><<)和逻辑 |&char 值吸收到 int 中。如果您使用 16 位或 64 位 ints 构建目标,还可以考虑使用 int32_t

【讨论】:

  • 为什么它适用于 const 值?我认为这将取决于编译器是否有效?
  • 常量值?我不明白你的意思。
  • 在我的示例中(至少在我的编译器中)d1 具有正确的值,但 d2 没有。
【解决方案2】:

没有办法,将指针转换为错误对齐的指针是未定义的。

您可以使用memcpychar 数组复制到int32_t

int32_t d = 0;
memcpy(&d, data+3, 4); // assuming sizeof(int) is 4

大多数编译器都为 memcpy 提供了内置函数,并带有一个恒定大小的参数,因此这很可能不会产生任何运行时开销。

即使正确对齐的指针允许像您展示的那样进行强制转换,但取消引用这样的指针还是违反了严格的别名。不能通过int 类型的左值访问有效类型为char[] 的对象。

一般来说,类型双关是字节序相关的,转换代表 RGB 颜色的 char 数组可能更容易以与字节序无关的方式进行,例如

int32_t d = (int32_t)data[2] << 16 | (int32_t)data[1] << 8 | data[0];

【讨论】:

  • 不是一个好主意。 C 不需要 char 是无符号的。如果char 已签名,则到int32_t 的转换将进行符号扩展,可能会将d 中的所有最高有效位设置为|
  • 不幸的是,我无法更改输入。这是在我的情况下给出的。我知道我可以通过换档等来做到这一点,但这要慢得多,而且这部分对性能非常关键。我希望有一种直接的方式,只需要大约一条指令而不是几条指令,因为数据在内存中的顺序已经正确......
  • @mafso:我明白了。但是,如果你 memcpy(),你真的不需要联合。 char 别名为int,您可以将memcpy() 直接转为int
  • @Karsten:你确定换挡太慢了吗?
  • @Karsten:好吧,如果你愿意接受一个“[...]不幸无法运行”的程序,我可以给你一个完全不需要时间运行的程序。为什么要比较工作程序的运行时间和非工作程序的运行时间?
猜你喜欢
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多