在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
)。但在这一点上,这将是一个更具侵略性的变化。我的问题是我是否可以通知gccxstpcpy
与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
行中发出了常规的(stpcpy)()
(libc调用)我本以为海合会会会降低到一个mempcpy
,因为stpcpy
builtin code in the gcc codebase made最初让我相信。命令行:
clang -O3 -save-temps -march=native stpcpy.c -o stpcpy
(XCode clang 3.4)克朗或多或少地有我从海合会期待的行为。它完全优化了对
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,我无法像clang那样用gcc创建类似的代码。
最佳答案
我不知道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
我只是试了一下,然后看了看装配台。使用memcpy
调用memcpy
。使用__builtin_memcpy
直接构建内存副本但是,如果将大小设置为大于8192,它将调用memcpy
函数这与使用-std=gnu99
相同。