我想将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);
}
我发现如果上面的源代码中的n
不是易变的,那么它会内置代码。但是,当n
变为易失性时,它会调用函数__memcpy_chk
,这是memcpy with buffer overflow checking的版本。如果n
不稳定,我会拨打__builtin_memcpy
,然后调用memcpy
。
所以到目前为止我的结论是,只有在编译时知道n
并且-fno-builtin
无效时才会生成内置代码。我正在使用GCC 4.8.2。
-fno-builtin
已过时吗?有没有办法在C库中调用memcpy
即使在编译时知道n
?
答案 0 :(得分:4)
-fno-builtin
和-fno-builtin-memcpy
都会产生您对gcc 4.9.1的预期效果。这可能只是gcc 4.8.2中的一个错误;这种特殊的选项组合并未得到广泛应用。 -ffreestanding
是一个相关的开关,可能具有您想要的效果4.8.2。
请注意,编译器可以将程序优化到
int main() { return 0; }
在没有-fno-builtin(-memcpy)
或-ffreestanding
的情况下调用,即使n
为volatile
,因为它(原则上)可以证明整个程序无法观察到副作用,或其行为未定义。 (当n
不 volatile
时,不能有UB;如果n
在读取时超出范围[0, 1000]
,则会发生UB,{ {1}}告诉编译器它不能假定volatile
具有程序写入它的值。)
答案 1 :(得分:1)
注意:因为您正在编译C ++代码,所以我不能100%确定是否适用。
C标准要求所有库函数(除非另有明确说明)具有地址,并且可以是&
地址运算符的操作数。这是因为它允许将一些/大多数函数实现为功能宏,但在某些情况下仍然应该像实际的变量/函数一样。为了避免它的宏版本,你只需要memcpy
令牌和(
令牌之间的某些东西(正如@Zach指出的那样,空格不足):
(memcpy)(y, x, ...)
这会强制使用实际的函数,应该避免任何类型的内置宏定义。
同样可能(阅读:可能)-O3
优化扫描某些函数调用(例如memcpy
)并用内置调用替换它们,而不管{{1} }。
答案 2 :(得分:1)
您的问题很可能是glibc,而不是gcc。您没有指定,但可能使用的是Ubuntu,默认情况下定义了-D_FORTIFY_SOURCE=2
。这会提示glibc标头提供memcpy
的内联定义,该定义转发到__memcpy_chk
。