例如,我想解析来自用户/stdin的输入,这个输入是一个字符串(char*
/char []
(。我知道我可以将字符串的内存地址指针类型转换为uint32_t
指针,并取消引用所述uint32_t
指针以提取unsigned int
值,这在大多数架构(我已经测试过(中是相同的。这安全吗?它会导致错误/未定义的行为吗?即一般来说是个坏主意?
示例:
#include <stdio.h>
#include <stdint.h>
int main(void) {
char data[] = "status";
printf("%un", *(uint32_t*)data);
return 0;
}
将导致64位和32位(windows和linux,未在MAC/unix系统上测试(上的1952543859
进行以下操作安全吗?:
char str_from_input[] = "status";
if (*(uint32_t*)str_from_input == 1952543859)
//... execute some code oriented around "status".
我的明显目的是通过不直接使用uint32_t
check/if语句重复调用像strcmp
和strncmp
这样的字符串解析函数来减少计算。
…将字符串的内存地址指针类型转换为uint32_t指针…这安全吗?
否。如果uint32_t
的字符串未正确对齐,则未定义强制转换的行为,根据C 2018 6.3.2.3 7:"…如果结果指针未正确对齐引用类型,则行为未定义…">
取消对结果指针的引用会使用不适合它的类型访问字符串,这违反了6.57中的混叠规则,而且C标准没有定义这种行为。
它会导致错误/未定义的行为吗?
是。
也就是说,总的来说,这是个坏主意吗?
是。
执行以下操作安全吗?:
否。
要将字符串中的字节重新解释为uint32_t
,请使用:
uint32_t t;
memcpy(&t, string, sizeof t);
printf("%" PRIu32 "n", t);
(memcpy
在<string.h>
中声明,PRIu32
在<inttypes.h>
中声明。(
要将uint32_t
的字节复制到字符串中,请使用memcpy(string, &t, sizeof t);
。
如果可行的话,一个好的C编译器可能会用直接的数据移动指令取代memcpy
调用。
我的明显目标是通过不直接使用
uint32_t
check/if语句重复调用strcmp
和strncmp
等字符串解析函数来减少计算。
避免使用拼凑。编写清晰的代码,让编译器进行优化。