use*_*276 21 c performance constants c-preprocessor
我最近想知道什么之间的区别#define,并static const在ç为什么两种方法存在做同样的事情.我发现有些人在这里有类似的问题:
很多人谈论最佳实践和约定,并给出使用一个在另一个上的实际原因,例如需要将指针传递给常量,我可以用a static const而不是a #define.但是我还没有找到任何人谈论两者效率的比较.
根据我对C预处理器的理解,如果我有这样的声明:
#define CONSTANT 6
Run Code Online (Sandbox Code Playgroud)
我创建一个可以像这样使用的常量值
char[CONSTANT]char[6]在实际编译之前, 它实际上将被替换为此语句.
这对我来说似乎比使用a更有效,
static const constant = 6;因为这将创建一个名为constant的变量,它将存在于堆栈中,我认为它会带来更多的行李而不是a #define.假设我需要一个常量,我可以选择使用预处理器#define或static const语句,没有明显的理由选择一个而不是另一个,哪个更有效?我将如何自己测试呢?
Ven*_*esh 35
考虑以下2个测试文件
Test1.c:使用静态const foo.
// Test1.c uses static const..
#include <stdio.h>
static const foo = 6;
int main() {
printf("%d", foo);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Test2.c:使用宏.
// Test2.c uses macro..
#include <stdio.h>
#define foo 6
int main() {
printf("%d", foo);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用gcc -O0(默认)时相应的程序集等价如下,
Test1.c的程序集:
0000000000000000 <main>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 48 83 ec 20 sub rsp,0x20
8: e8 00 00 00 00 call d <main+0xd>
d: b8 06 00 00 00 mov eax,0x6
12: 89 c2 mov edx,eax
14: 48 8d 0d 04 00 00 00 lea rcx,[rip+0x4] # 1f <main+0x1f>
1b: e8 00 00 00 00 call 20 <main+0x20>
20: b8 00 00 00 00 mov eax,0x0
25: 48 83 c4 20 add rsp,0x20
29: 5d pop rbp
2a: c3 ret
2b: 90 nop
Run Code Online (Sandbox Code Playgroud)
Test2.c的程序集:
0000000000000000 <main>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 48 83 ec 20 sub rsp,0x20
8: e8 00 00 00 00 call d <main+0xd>
d: ba 06 00 00 00 mov edx,0x6
12: 48 8d 0d 00 00 00 00 lea rcx,[rip+0x0] # 19 <main+0x19>
19: e8 00 00 00 00 call 1e <main+0x1e>
1e: b8 00 00 00 00 mov eax,0x0
23: 48 83 c4 20 add rsp,0x20
27: 5d pop rbp
28: c3 ret
29: 90 nop
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,都没有使用外部存储器.但不同之处在于,#define用foo值替换static const是指令,因此它将指令指针递增到下一条指令,并使用1个额外的寄存器来存储该值.
通过这个,我们可以说宏比静态常量好,但差异是最小的.
编辑:当使用-O3编译选项(即在优化时),test1.c和test2.c都评估相同.
0000000000000000 <main>:
0: 48 83 ec 28 sub rsp,0x28
4: e8 00 00 00 00 call 9 <main+0x9>
9: 48 8d 0d 00 00 00 00 lea rcx,[rip+0x0] # 10 <main+0x10>
10: ba 06 00 00 00 mov edx,0x6
15: e8 00 00 00 00 call 1a <main+0x1a>
1a: 31 c0 xor eax,eax
1c: 48 83 c4 28 add rsp,0x28
20: c3 ret
21: 90 nop
Run Code Online (Sandbox Code Playgroud)
因此,在优化时gcc对待它们static const并#define同样对待它们.
测试简单优化问题的快速方法是使用Godbolt。
对于您的特定问题,现代优化编译器应该能够为这两种情况生成相同的代码,并且实际上只是将它们优化为常量。我们可以通过以下程序看到这一点(现场观看):
#include <stdio.h>
#define CONSTANT 6
static const int constant = 6;
void func()
{
printf( "%d\n", constant ) ;
printf( "%d\n", CONSTANT ) ;
}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,访问都减少到以下内容:
movl $6, %esi #,
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15478 次 |
| 最近记录: |