c - 如何使用 -Os 强制 GCC 编译器在编译时计算常量

标签 c gcc optimization compile-time-constant constant-expression

我尝试使用宏在编译时计算常量 C 字符串的哈希值。这是我的示例代码:

#include <stddef.h>
#include <stdint.h>

typedef uint32_t hash_t;

#define hash_cstr(s) ({           \
      typeof(sizeof(s)) i = 0;    \
      hash_t h = 5381;            \
      for (; i < sizeof(s) - 1; ) \
        h = h * 33 + s[i++];      \
      h;                          \
    })

/* tests */
#include <stdio.h>

int main() {
#define test(s) printf("The djb2 hash of " #s " is a %u\n", hash_cstr(#s))

  test(POST);
  test(/path/to/file);
  test(Content-Length);
}

现在我运行GCC来显示列表:

arm-none-eabi-gcc-4.8 -S -O2 -funroll-loops -o hash_test.S hash_test.c

结果正如预期的那样:所有字符串都被消除并替换为它的哈希值。但通常我使用-Os来编译嵌入式应用程序的代码。当我尝试这样做时,我仅对少于四个字符的字符串进行哈希。我还尝试设置参数 max-unroll-times 并使用 GCC 4.9:

arm-none-eabi-gcc-4.9 -S -Os -funroll-loops \
  --param max-unroll-times=128 -o hash_test.S hash_test.c

我无法理解这种行为的原因以及如何扩展此四个字符的限制。

最佳答案

我建议将相关代码放在一个单独的文件中,并使用 -O2 (而不是使用 -Os)编译该文件。或者输入function specific pragma喜欢

 #pragma GCC optimize ("-O2")

在函数之前,或者使用 function attribute就像 __attribute__((optimize("02"))) (并且 pure 属性可能也相关)

您可能对 __builtin_constant_p 感兴趣.

我会让你的哈希代码成为一些静态内联函数(可能带有always_inline函数属性),例如

 static inline hash_t hashfun(const char*s) {
    hash_t h = 5381;
    for (const char* p = s; *p; p++) 
      h = h * 33 + *p;
    return h;
 }

一个更便携(且更不易损坏)的替代方案是更改构建过程以生成一些 C 文件(例如,使用简单的 awkpython 脚本,甚至是一个临时 C 程序)包含诸如

之类的内容
  const char str1[]="POST";
  hash_t hash1=2089437419; // the hash code of str1

不要忘记 .c.h 文件可以由其他东西生成(您只需要在 Makefile 中添加一些规则即可 生成它们);如果你的老板对此感到不安,请向他展示 metaprogramming维基页面。

关于c - 如何使用 -Os 强制 GCC 编译器在编译时计算常量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34333936/

相关文章:

c - 简单的 C 菜单构建,Scanf 不拖拉输入

c++ - gcc:带有 Wextra 和成员初始化的 weffc++

python - 优化二维数组中所有元素的舍入

optimization - 这个时钟什么时候买的?

c - 在 C 中使用数组计算分数

c - XINU OS - 理解 roundmb 函数

c - 如何解析结构变量

c++ - 我怎样才能让 GCC/Clang 警告使用未初始化的成员?

c - 线程还是进程?拥有与数据无关的任务,使用什么更好?

java - 使用 UTF-16LE 编码将 String 快速转换为 byte[]