【发布时间】:2014-09-04 14:40:20
【问题描述】:
在 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,我无法像clang那样使用gcc创建类似的代码。
【问题讨论】:
-
@technosaurus:我想知道
-fno-builtin的反面。 -
@technosaurus
-fno-builtin仅适用于 GCC 4.9.x stackoverflow.com/questions/25272576/… -
-fno-builtin存在的时间比 4.9 还要长... -fbuiltin(如果存在的话)是默认行为,除非指定了-fno-builtin或-ffreestanding。使用 -std=*** 更改其中任何一个都没有意义,因为该行为是实现定义的,而不是标准。尽管我不想推荐它,但 autotools 就是为这种情况而设计的。 -
@technosaurus,您阅读链接了吗?您是否尝试使用
-fno-builtin与例如GCC 4.8.1 并查看程序集? -
@Zboson gcc.godbolt.org 使用
g++,而不是gcc并且 -fno-builtin 失败的任何版本都是该版本中的错误(另请注意,4.8 是第一个使用的版本C ++,因此预计会出现新错误)自动工具通常会为编译器错误添加解决方法(这就是为什么配置脚本最终可能是实际代码大小的 100 倍)...如果您想确保使用库函数(强制不使用内置函数)你可以像(function_name)(parameters,...)那样调用它而不是function_name(parameters,...)...注意函数名周围的括号。
标签: c gcc clang posix built-in