gcc 何时在编译时评估函数?

use*_*684 2 c gcc

当我有以下代码时

int main(void) {
        printf("%zd\n", strlen("Hello World!"));

        return 0;
}
Run Code Online (Sandbox Code Playgroud)

并用 编译它-O3strings将显示字符串“Hello World!” 二进制文件中缺少它,因为它在编译时进行了评估。

如果我改为使用我自己的函数

static inline size_t my_strlen(const char *s) {
        const char *tmp = s;

        while (*++tmp);

        return tmp - s;
}

int main(void) {
        printf("%zd\n", my_strlen("Hello World!"));

        return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用相同的选项,仍然可以在二进制文件中找到该字符串。

为什么是这样?

Bas*_*tch 5

因为这是标准允许的优化

在某些系统上,strlen最终扩展为_builtin_strlenGCC 编译器所知道的。在我的机器上/usr/include/x86_64-linux-gnu/bits/string.h(由间接包含<string.h>)有

# define strlen(str) \
  (__extension__ (__builtin_constant_p (str)         \
                 ? __builtin_strlen (str)            \
                 : __strlen_g (str)))
Run Code Online (Sandbox Code Playgroud)

所以实际上它是由 GNUglibcgcc