【问题标题】:Compare string with uint32_t by dereference通过取消引用将字符串与 uint32_t 进行比较
【发布时间】:2021-07-14 02:21:52
【问题描述】:

比如说我想解析来自用户/标准输入的输入,这个输入是一个字符串(char*/char [])。我知道我可以将字符串的内存地址指针类型转换为uint32_t 指针并取消引用uint32_t 指针以提取unsigned int 值,这在大多数体系结构中都是相同的(我已经测试过)。这安全吗?它会导致错误/未定义的行为吗?即一般来说是个坏主意?

例子:


#include <stdio.h>
#include <stdint.h>

int main(void) {
    char data[] = "status";
    printf("%u\n", *(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 语句不重复调用strcmpstrncmp 等字符串解析函数来减少计算量。

【问题讨论】:

  • (uint32_t*)data 是一个问题,如果它不满足uint32_t 的对齐要求。使用memcpy()
  • 对齐要求是指严格的别名?如果我将数据 memcpy 到 unit32_t 内存位置,代码是否会正确,这将是安全的
  • dkkl_codex,我的评论是关于对齐,而不是别名。 IAC,你在下面有一个很好的答案。
  • "明显的目的是减少计算量..." --> Is premature optimization really the root of all evil?

标签: c parsing input cross-platform unsigned-integer


【解决方案1】:

... 将字符串的内存地址指针类型转换为 uint32_t 指针... 这安全吗?

没有。如果字符串未正确对齐 uint32_t,则未定义强制转换的行为,根据 C 2018 6.3.2.3 7:“……如果结果指针未正确对齐引用类型,则行为未定义…… ”

取消引用结果指针会使用不适合它的类型访问字符串,违反了 6.5 7 中的别名规则,并且行为未由 C 标准定义。

它会导致错误/未定义的行为吗?

是的。

即总的来说是个坏主意?

是的。

进行以下操作是否安全?:

没有。

要将字符串中的字节重新解释为uint32_t,请使用:

uint32_t t;
memcpy(&t, string, sizeof t);
printf("%" PRIu32 "\n", t);

memcpy&lt;string.h&gt;中声明,PRIu32&lt;inttypes.h&gt;中声明。)

要将uint32_t 的字节复制到字符串中,请使用memcpy(string, &amp;t, sizeof t);

如果可行的话,一个好的 C 编译器可能会用直接数据移动指令替换 memcpy 调用。

我的明显目标是通过直接uint32_t check/if 语句不重复调用strcmpstrncmp 等字符串解析函数来减少计算量。

避免使用杂物。编写清晰的代码,让编译器优化。

【讨论】:

  • 所以我应该只使用strcmp/strncmp 换句话说?除非我用memcpy?
  • 那么调用memcpy + if 语句来检查uint32_t 值,就像在我的示例中一样,除了没有重新解释强制转换之外,是否比调用strcmpstrncmp 更快?
  • 别再找麻烦了。写strcmpstrncmp 来比较字符串或其中的一部分。不要担心它们的性能,直到它真正损害您的应用程序或您具备详细分析性能所需的专业知识。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-04
  • 2012-10-06
  • 2019-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多