C++ 带有-fno内置项的GCC似乎不起作用

C++ 带有-fno内置项的GCC似乎不起作用,c++,gcc,memcpy,C++,Gcc,Memcpy,我想将GCC内置函数memcpy与libc中的函数进行比较。但是,似乎忽略了-fno-builtin或-fno-builtin memcpy的所有迭代 //g++ -O3 foo.cpp -S or //g++ -O3 -fno-builtin foo.cpp -S #include <string.h> int main() { volatile int n = 1000; //int n = 1000; float *x = new float[1000]

我想将GCC内置函数
memcpy
与libc中的函数进行比较。但是,似乎忽略了
-fno-builtin
-fno-builtin memcpy
的所有迭代

//g++ -O3 foo.cpp -S or
//g++ -O3 -fno-builtin foo.cpp -S
#include <string.h>
int main() {
    volatile int n = 1000;
    //int n = 1000;
    float *x = new float[1000];
    float *y = new float[1000];
    memcpy(y,x,sizeof(float)*n);
    //__builtin_memcpy(y,x,sizeof(float)*n);    
}
//g++-O3 foo.cpp-S或
//g++-O3-fno内置foo.cpp-S
#包括
int main(){
挥发性int n=1000;
//int n=1000;
浮动*x=新浮动[1000];
浮动*y=新浮动[1000];
memcpy(y,x,sizeof(float)*n);
//__内置内存(y、x、尺寸(浮动)*n);
}
我发现,如果上述源代码中的
n
不是易失性的,那么它会内联内置代码。但是,当
n
变为易失性时,它将调用函数
\uuu memcpy\u chk
,该函数是的一个版本。如果
n
是易失性的,而我调用
\uu builtin\u memcpy
,那么它调用
memcpy

因此,到目前为止,我的结论是,只有在编译时已知
n
时才会生成内置代码,
-fno-builtin
是无用的。我使用的是GCC4.8.2


-fno内置
是否过时?是否有一种方法可以从C库中调用GCC调用<代码> MycPy < /> >,即使在编译时知道代码> N>代码>?< P> > P>注释:因为您正在编译C++代码,如果应用了,我不确定100%。
C标准要求所有库函数(除非另有明确指示)都有一个地址,并且可以是
&
地址运算符的操作数。这是因为它允许某些/大多数函数作为函数宏实现,但在某些情况下仍应表现为实际变量/函数。为了避免使用它的宏版本,您只需要在
memcpy
标记和
标记(正如@Zach指出的,空格不够)之间添加一些内容:

这将强制使用实际函数,这将避免任何类型的内置宏定义



-O3
优化也可能扫描某些函数调用(例如
memcpy
)并用内置调用替换它们,而不考虑
-fno-builtin

-fno-builtin
-fno-builtin memcpy
这两个选项都具有gcc 4.9.1所期望的效果。这可能只是gcc 4.8.2中的一个错误;这种特定的选项组合没有被广泛使用。
-ffreserving
是一个相关的开关这可能会对4.8.2产生您想要的效果

请注意,编译器有权将您的程序优化到

int main() { return 0; }

当调用时没有
-fno内置(-memcpy)
-f重新理解
,即使
n
易变的
,因为它可以(原则上)证明程序作为一个整体没有可观察到的副作用,或者其行为是未定义的。(当
n
不是
volatile
时,就不会有UB;如果读取时
n
[0,1000]
范围之外,并且
volatile
告诉编译器它不能假定
n
有程序写入的值,就会发生UB。)您的问题很可能是glibc,而不是gcc。您没有指定,但您可能正在使用Ubuntu,默认情况下它定义了
-D\u FORTIFY\u SOURCE=2
。这会提示glibc头提供
memcpy
的内联定义,并转发到
\u memcpy\u chk

一个
memcpy
的宏版本仍将在
memcpy
。但是,在标记
memcpy
周围加上括号确实符合您的描述。此外,我可以权威地说,
-fno-builtin
在所有优化级别上都应该满足OP的期望。我用GCC和g+尝试了您的建议(这个代码在C中编译得很好,所以我不确定C++标签是否更好),它们没有区别。就像“代码> -O3
作为下一个预处理标记)”开头的句子(我的重点是:空格不是预处理标记))显然(如果您习惯了standardese,那么)表示函数宏是扩展的,即使宏名称和
(2/2)之间存在任何数量的空格我尝试了
-ff重新理解
。这没有什么区别。我必须安装gcc 4.9.1来验证您的答案。我查看了
http://gcc.godbolt.org/
,我可以确认
-fno-builtin
按照GCC 4.9中的预期工作,而不是GCC 4.8.1中的预期工作。我检查了GCC 4.4至4.9,并且4.9是唯一得到它的rect.ICC也是正确的。当我传递
-fno-builtin
时,它使用
memcpy
,没有它,它使用
\u intel\u fast\u memcpy
。很明显,编译器没有优化代码。从汇编程序代码中可以看出这一点。我刚刚注意到,在这个问题和您的评论中,您拼写错误
-fno-builtin
几种不同的方法。检查以确保不会影响结果。正确的拼写是“bu i l t i n”。@Zack,谢谢你找到拼写错误。我希望我都解决了。我确实有点太马虎了(当我在测试示例中应该使用malloc时,我也使用了
new
——在我自己的代码中,我使用了
\u mm\u malloc
)。但是GCC会抱怨我是否使用了任何拼写错误。但是如果你想自己检查,请将代码放在int上面(删除volatile)
int main() { return 0; }