static const
变量;当程序被加载时,它们的空间被放置在一边,所以不应该存在与它们的创建相关的运行时间损失。
有可能与他们的初始化相关联的运行时间延长。虽然我使用的gcc版本在编译时初始化常量,我不知道这种行为有多普遍。如果有这样的运行时间损失,它只会在程序启动时出现一次。
除此之外,静态const
-qualified对象和之间的运行时性能差异文字(这是一个宏最终会扩大到)应该是可以忽略不计,以不存在的,根据字面的类型和涉及的操作。
笨示例(gcc version 4.1.2 20070115 (SUSE Linux)
):
#include <stdio.h>
#define FOO_MACRO 5
static const int foo_const = 5;
int main(void)
{
printf("sizeof FOO_MACRO = %zu\n", sizeof FOO_MACRO);
printf("sizeof foo_const = %zu\n", sizeof foo_const);
printf(" &foo_const = %p\n", (void *) &foo_const);
printf("FOO_MACRO = %d\n", FOO_MACRO);
printf("foo_const = %d\n", foo_const);
return 0;
}
输出:
sizeof FOO_MACRO = 4
sizeof foo_const = 4
&foo_const = 0x400660
FOO_MACRO = 5
foo_const = 5
的foo_const
地址是二进制的.rodata
部分:
[[email protected]]~/prototypes/static: objdump -s -j .rodata static
static: file format elf64-x86-64
Contents of section .rodata:
40065c 01000200 05000000 73697a65 6f662046 ........sizeof F
^^^^^^^^
40066c 4f4f5f4d 4143524f 203d2025 7a750a00 OO_MACRO = %zu..
40067c 73697a65 6f662066 6f6f5f63 6f6e7374 sizeof foo_const
40068c 203d2025 7a750a00 20202020 20202666 = %zu.. &f
40069c 6f6f5f63 6f6e7374 203d2025 700a0046 oo_const = %p..F
4006ac 4f4f5f4d 4143524f 203d2025 640a0066 OO_MACRO = %d..f
4006bc 6f6f5f63 6f6e7374 203d2025 640a00 oo_const = %d..
注意,目的是已经初始化为5,所以没有runtim初始化惩罚。
在printf
语句,向foo_const
值加载到%esi
该指令需要一个比加载字面值0x5
多一个字节,并且指令具有有效地取消引用%rip
寄存器:
400538: be 05 00 00 00 mov $0x5,%esi
^^^^^^^^^^^^^^
40053d: bf ab 06 40 00 mov $0x4006ab,%edi
400542: b8 00 00 00 00 mov $0x0,%eax
400547: e8 e4 fe ff ff callq 400430 <[email protected]>
40054c: 8b 35 0e 01 00 00 mov 270(%rip),%esi # 400660 <foo_const>
^^^^^^^^^^^^^^^^^
400552: bf bb 06 40 00 mov $0x4006bb,%edi
400557: b8 00 00 00 00 mov $0x0,%eax
40055c: e8 cf fe ff ff callq 400430 <[email protected]>
这会转化为可衡量的运行时间性能差异吗?也许,在正确的环境下。如果你在一个紧密的循环中CPU约束数十万次,那么是的,使用一个宏(解析为文字)在static const
变量可能可测量得更快。如果这是在程序的整个生命周期中发生的一次,那么差异太小而无法测量,并且没有强制性的理由使用宏来替代static const
变量。
一如既往,正确性和可维护性比性能更重要。使用static const
代替宏,你不太可能犯错。考虑以下情形:
#define FOO 1+2
...
x = FOO * 3;
什么答案,你会期望,什么答案,你会得到?相比之下,与
static const int foo = 1+2;
...
x = foo * 3;
是的,你可以通过使用括号解决宏观情况 - (1 + 2)
。问题是,如果您使用static const
对象,则此场景不是问题。这是一个少开一枪的方式。
1.现在,我只是说说简单的标文字(整数或浮点数),而不是复合文字;没有调查他们的行为。
2.如果你的代码给你错误的答案或做错了什么,它的速度有多快并不重要。如果没有人能够修复或升级它,因为他们无法理解它的工作方式,那么代码的速度有多快并不重要。如果代码在第一次错误输入提示时死了,代码速度有多快并不重要。如果代码打开恶意软件的大门,代码速度有多快并不重要。
我不明白为什么编译器不应该代替'静态的,我们可以用下面的程序(see it live)看到这const int foo = 6'在编译时带有文字“6”。 – Philipp 2014-11-21 18:59:14
#define'd常量实际上只存在于源代码和编译器中。它的价值将会被放置在任何使用它的地方,例如'FOO(恒定)'。一个'静态常量常量'将为变量本身分配一些永久存储空间,并且它的每个地方都会引用这个值。对于一个简单的字符,这是一个微不足道的节省 - 内部的变量指针/引用将比“char”更大。但是如果这个价值更长,那么常数会更便宜。 – 2014-11-21 19:01:56
你正在做一个假设,“恒定”会在栈上生活。一个优化编译器可以(通常会)只是用'6'替换名字'constant',就像使用宏一样。所以不,你不会通过使用宏来获得任何速度(加上,即使它确实有所作为,你正在谈论一个微型优化,这对你的代码性能影响可能微乎其微)。 – Cornstalks 2014-11-21 19:03:13