在neovim项目中,我们使用了一些标准功能,但并没有在所有目标平台上实现值得注意的是,stpcpy而且很快也mempcpyCurrently 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)。但在这一点上,这将是一个更具侵略性的变化。我的问题是我是否可以通知gccxstpcpystpcpy完全相同?
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,因为stpcpybuiltin 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-builtinonly seems to work for GCC 4.9.x
编辑:
要使用-std=c99的内置项,请使用__builtin_memcpy我只是试了一下,然后看了看装配台。使用memcpy调用memcpy。使用__builtin_memcpy直接构建内存副本但是,如果将大小设置为大于8192,它将调用memcpy函数这与使用-std=gnu99相同。

09-16 10:09