在 neovim 项目中,我们使用了一些标准功能,但并未在所有目标平台上实现。值得注意的是,stpcpy
以及即将推出的 mempcpy
。 Currently we're solving that by supplying and using our own x
variants of these functions .
一个例子:
char *xstpcpy(char *restrict dst, const char *restrict src)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
const size_t len = strlen(src);
return (char *)memcpy(dst, src, len + 1) + len;
}
然而,这仍然不是完全最优的,因为一些编译器,如 gcc,知道这些函数的标准版本是做什么的,并且在给定足够的上下文时可以生成更好的代码:gcc code for stpcpy builtin .
我想在它们周围放置 #ifdef
守卫,只有当它们未定义时才应由我们提供,并且我们应该开始使用常规名称(stpcpy
而不是 xstpcpy
)。但在这一点上,这将是一个更具侵入性的变化。我的问题是我是否可以通过其他方式通知 gcc xstpcpy
与 stpcpy
完全一样?
P.S.:一个相关的问题:是否有一个标志,例如 -std=c99
,强制 gcc/clang 无论如何发出对标准函数的调用?我好像记得有这么一件事,但现在找不到相关资料了。如果 -std=c99
确实禁用了内置扩展,我想知道如何在保持 -std=c99
的同时启用内置扩展。
编辑:由于一切似乎都有些模糊,我一直在尝试一些事情。先上代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
const char str[] = "we have stpcpy";
printf("static\n");
{
char p1[256];
char p2[256];
char *end1 = stpcpy(p1, str);
char *end2 = (stpcpy)(p2, str);
printf("static using stpcpy?\np1 = %s (end = %p)\np2 = %s (end = %p)\n",
p1, end1, p2, end2);
}
return 0;
}
结果(我在 OSX 上,但 godbolt 表明它在 linux 上类似):
命令行:gcc-4.9 -O3 -save-temps -march=native stpcpy.c -o stpcpy
gcc 4.9 似乎发出对 stpcpy_chk
的调用来代替 stpcpy()
行,并发出常规 _stpcpy
(libc 调用)来代替(stpcpy)()
行。我本来希望 gcc 将其降低为 mempcpy
作为 stpcpy
builtin code in the gcc codebase made最初让我相信。
命令行:clang -O3 -save-temps -march=native stpcpy.c -o stpcpy
(XCode clang 3.4)
Clang 或多或少具有我对 gcc 的预期行为。它完全优化了对 stpcpy
的调用。像这样创建 asm:
leaq -258(%rbp), %rdx
movabsq $34182044572742432, %rax ## imm = 0x79706370747320
movq %rax, -265(%rbp)
movabsq $2334402142592329079, %rcx ## imm = 0x2065766168206577
movq %rcx, -272(%rbp)
而不是调用 _stpcpy
。
我想知道我是否可以让 gcc-4.9 做我想做的事。在不同版本中使用 godbolt,我无法使用 gcc 创建与 clang 类似的代码。
最佳答案
我不知道 stpcpy
的内置函数是如何工作的,但是对于 memcpy
它要求大小是一个编译时间常数并且小于或等于 8192 字节。如果您的代码满足这两个要求(并且您不使用 -fno-builtin
),GCC 将使用内置的 memcpy
。我不知道有什么方法可以强制它使用 builtin
来获得更大的尺寸。
要禁用内置函数,您可以使用 -fno-builtin
。但是,-fno-builtin
only seems to work for GCC 4.9.x .
编辑:
要将内置函数与 -std=c99
一起使用,请使用 __builtin_memcpy
。我只是试过这个并查看了 assemblby。使用 memcpy
调用 memcpy
。使用 __builtin_memcpy
直接构建内存副本。但是,如果您设置的大小大于 8192,它会调用 memcpy
函数。这与使用 -std=gnu99
相同。
关于c - 使 gcc/clang 将函数识别为内置函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25668350/