将字符数组转换为整数

4

编辑:num2的错误类型已经被更正。

你好,

我有一些已知大小的字符数组,其中包含从二进制文件中读取的原始整数数据。

所有这些数组的大小都是一个整数。

我想问,在所有正常情况下,假设原始数据的字节顺序和运行此代码的计算机相同,以下操作是否安全且准确。

char arr1[4] = { ... };
char arr2[2] = { ... };

uint32_t num1 = *static_cast<uint32_t*>(arr1); /* OR num1 = *(uint32_t*)arr1 in C */
uint16_t num2 = *static_cast<uint16_t*>(arr2); /* OR num2 = *(uint32_t*)arr2 in C */

谢谢你!


3
因为这是一个二进制文件,你最好将原始的整数读入一个int数组中。 - chrisaycock
1
不要同时声明多个变量,这可能会导致难以察觉的错误。https://www.securecoding.cert.org/confluence/display/seccode/DCL04-C.+Do+not+declare+more+than+one+variable+per+declaration - aaaa bbbb
将字符内存直接转换为整数仅适用于字节对齐的CPU,不适用于字对齐的CPU。如果你只使用Intel x86 CPU,那就不会有问题。 - David R Tribble
@chrisaycock 好吧...其实我是...(顺便说一下,我觉得同时声明>1个变量没有任何问题...我认为这只是个人喜好。) - Ron Lau
6个回答

5
你应该使用联合体。
union charint32 {
    char arr1[4];
    uint32_t num;
};

这将为您简化存储和转换过程。

1
只要字节顺序相同,这将起作用,并且不会有数据类型对齐问题。 - David R Tribble
+1。这个会起作用。虽然它不符合C++标准,但这可能是最常被违反的规则之一。 - EboMike

3

从技术角度来看,这是安全的,但有几个需要考虑的事情:

  • 添加编译时断言来验证大小。你确定你的 char 数组等于 sizeof(your_int_type)?你的 num2 是为什么很重要的例子 - 你的拼写错误会导致未定义的行为。
  • 考虑对齐方式。你确定你的 char 数组在 4 字节边界上(假设你的 int 是 4 字节)?例如,PowerPC 将崩溃,如果你尝试从非对齐指针读取 int。

在我的程序中,通过一些模板元编程代码确定了相应整数的类型,因此可以确保正确的类型。 - Ron Lau
1
有没有办法验证字符数组是否真的在4字节边界上? - Ron Lau
获取它的地址并检查其对齐方式。 - EboMike
Ron - 就这样吧。显然,您会想使用 sizeof(type) 而不是 4。或者,如果你想要花哨一些,并且确定 sizeof 是2的次幂,你可以使用 !(arr & (sizeof(type)-1))。但在这种情况下,使用 % 更安全,因为它仅用于验证,所以我绝对会使用那个。 - EboMike
叹气,90年代中期我是一个坚定的反英特尔者,坚持购买AMD CPU。现在看看我变成了什么样子。变老会让你变得可怕。不幸的是,现在已经太晚修改我的评论了,但感谢您指出这一点(并让我感到惭愧:))。 - EboMike
显示剩余3条评论

1

这应该是安全的:

char arr1[4] = { ... };

uint32_t num1;

memcpy(&num1, arr1, sizeof num1);

但是为什么arr2只有2个字节大小?这是打印错误吗?


只要你控制代码部署的位置,你就有。 - David R Tribble

0
一个更安全的方法是使用宏(例如MAKEDWORD)将字节按正确顺序放置。

0
如果您确定数组已正确对齐,则不应该有问题(考虑字节序)。
但是,在代码中,我不知道您对arr2做了什么,因为它是16位的,而您正在从中读取32位的数量。

0

是的,在您假设字节序正确的情况下,这应该可以正常工作,因为这些字节在内存中的表示方式无论是作为字节数组还是整数解释都是相同的。

实际上,您所做的只是更改类型,而不是数据本身。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接