我为这样的代码尝试了 gcc (9.2.1) 和 clang (9.0.1) 的最新版本:
//pure.cpp
int square (int x) __attribute__ ((pure));
int square (int x)
{
return x * x;
}
//test.cpp
#include <stdio.h>
int square (int x) __attribute__ ((pure));
int main(int argc, char *argv[])
{
const int same = argc;
printf("result: %d\n", square(same));
printf("result2: %d\n", square(same));
}
Run Code Online (Sandbox Code Playgroud)
并像这样编译它:
g++ -ggdb -Ofast -c test.cpp
g++ -ggdb -Ofast -c pure.cpp
g++ -ggdb -Ofast -o test test.o pure.o
Run Code Online (Sandbox Code Playgroud)
结果我看到:
1043: e8 58 01 00 00 callq 11a0 <_Z6squarei>
1048: 48 8d 3d b5 0f 00 00 lea 0xfb5(%rip),%rdi # 2004 <_IO_stdin_used+0x4>
104f: 89 c6 mov %eax,%esi
1051: 31 c0 xor %eax,%eax
1053: e8 d8 ff ff ff callq 1030 <printf@plt>
printf("result2: %d\n", square(same));
1058: 89 ef mov %ebp,%edi
105a: e8 41 01 00 00 callq 11a0 <_Z6squarei>
105f: 48 8d 3d aa 0f 00 00 lea 0xfaa(%rip),%rdi # 2010 <_IO_stdin_used+0x10>
1066: 89 c6 mov %eax,%esi
1068: 31 c0 xor %eax,%eax
106a: e8 c1 ff ff ff callq 1030 <printf@plt>
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,有两个调用_Z6squarei,但为什么呢?我将函数标记为纯函数,并使用相同的参数,为什么 gcc 和 clang 无法删除第二个调用?
问题是,虽然square()标记为纯,但printf()不是。因此,编译器不能随意假设调用 后所有状态都相同printf(),因此square()它本身可能会读取不同的状态,从而产生不同的输出。但是,如果您调用square()两次而中间没有任何其他函数调用,应该没问题:
int main(int argc, char *argv[])
{
const int same = argc;
int x = square(same);
int y = square(same);
printf("result: %d\n", x);
printf("result2: %d\n", y);
}
Run Code Online (Sandbox Code Playgroud)
正如 eerorika 所提到的,__attribute__((const))它将起作用,因为它增加了进一步的限制,square()除了其输入外,可能无法读取任何状态。请参阅有关 pure 和 const 之间区别的问题。
| 归档时间: |
|
| 查看次数: |
95 次 |
| 最近记录: |