我们的C代码库跨两个文件存储所有全局常量:
//global.h
extern const long double ACCELERATION_GRAVITY_FTS;
extern const long double PI;
extern const long double DEG_TO_RAD;
extern const long double RAD_TO_DEG;
extern const long double GC_NM_PER_RAD;
extern const long double FEET_PER_NM;
...
//global.c
const long double ACCELERATION_GRAVITY_FTS = 32.17405;
const long double PI = 3.1415926535897932384626433832795;
const long double DEG_TO_RAD = 0.01745329251994329576923690768489;
const long double RAD_TO_DEG = 57.295779513082320876798154814105;
const long double GC_NM_PER_RAD = 3437.74677471314;
const long double FEET_PER_NM = 6076.1155;
为了避免重复,我想将它们重构为一个文件:
//global.h
static const long double ACCELERATION_GRAVITY_FTS = 32.17405;
static const long double PI = 3.1415926535897932384626433832795;
static const long double DEG_TO_RAD = 0.01745329251994329576923690768489;
static const long double RAD_TO_DEG = 57.295779513082320876798154814105;
static const long double GC_NM_PER_RAD = 3437.74677471314;
static const long double FEET_PER_NM = 6076.1155;
//global.c no longer exists
尽管从可维护性的角度来看,这显然是一个很好的重构,
对于性能和可执行文件大小是否实用?
最佳答案
除非static const
或由函数初始化,否则volatile
变量将是编译时常量。
(无论如何,使用任何合适的优化编译器)
所以如果你使用static const
变量,你可以得到一个速度增加和一个更小的二进制数。
例如:
extern volatile const int n;
int main(){
volatile int i = n;
}
volatile const int n = 5;
其中包含x86程序集:
main:
mov eax, DWORD PTR n[rip]
mov DWORD PTR [rsp-4], eax
xor eax, eax
ret
n:
.long 5
我们必须使用
volatile
来强制编译器获取变量的地址(如果变量不是volatile
而是在另一个转换单元中,则会发生这种情况),而不是优化int i
。与
static const
相同的例子:static const int n = 5;
int main(){
volatile int i = n;
}
具有x86程序集:
main:
mov DWORD PTR [rsp-4], 5
xor eax, eax
ret
我们不必对常量使用
volatile
,因为我们将以与使用头完全相同的方式公开变量,但是我们仍然需要停止编译器优化i
。您可以看到,
static const
方法少了一条指令,extern
方法在二进制文件中添加了额外的数据,用于需要存储以供参考的文本。所以我们得到了更好的性能和更小的二进制文件。尽管,我承认,这些例子都是微不足道的。
实际上,这也不是一个完美的表现。如果在另一个翻译单元中定义了
const int n
,如果没有链接时间优化,编译器将无法输出n: .long 5
,并且必须引用另一个变量。但我们会给这个例子带来怀疑的好处。这些优化是非常常见的,您基本上可以依赖它的可用性。
唯一要注意的是如果你写了这样的东西:
static const int n = some_func();
int main(){
volatile int i = n;
}
编译器将无法用
n
替换其文本值。这会给二进制文件添加膨胀,因为您在头中定义它,并且它将在每个转换单元中重新声明一次。因此,在这种情况下,extern
对空间更有利,但可能不是在速度上;您可以自己测试。如果你真的需要微观优化,只需混合和匹配。[所有示例都是用GCC4.9.2从https://gcc.godbolt.org/中编译的,并使用标志-O3]
关于c - 用“静态常量”替换“外部常量”会影响性能吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32491639/