我已经阅读了关于该主题的几个问题:
- Should I use #define, enum or const?
- How does Enum allocate Memory on C?
- What makes a better constant in C, a macro or an enum?
- What is the size of an enum in C?
- "static const" vs "#define" vs "enum"
- static const vs. #define in c++ - differences in executable size
而且我知道在 #define
宏中通常首选枚举以获得更好的封装和/或可读性。此外,它还允许编译器检查类型以防止出现某些错误。
const
声明介于两者之间,允许类型检查和封装,但更困惑。
现在我在内存空间非常有限的嵌入式应用程序中工作(我们经常不得不为节省字节而战)。我的第一个想法是常量比枚举占用更多的内存。但我意识到我不确定常量将如何出现在最终固件中。
例子:
enum { standby, starting, active, stoping } state;
问题
在资源有限的环境中,enum
vs #define
vs static const
在执行速度和内存印记方面如何比较?
最佳答案
为了尝试获得答案的一些实质性要素,我做了一个简单的测试。
代码
我写了一个简单的 C 程序main.c:
#include <stdio.h>
#include "constants.h"
// Define states
#define STATE_STANDBY 0
#define STATE_START 1
#define STATE_RUN 2
#define STATE_STOP 3
// Common code
void wait(unsigned int n)
{
unsigned long int vLoop;
for ( vLoop=0 ; vLoop<n*LOOP_SIZE ; ++vLoop )
{
if ( (vLoop % LOOP_SIZE) == 0 ) printf(".");
}
printf("\n");
}
int main ( int argc, char *argv[] )
{
int state = 0;
int loop_state;
for ( loop_state=0 ; loop_state<MACHINE_LOOP ; ++loop_state)
{
if ( state == STATE_STANDBY )
{
printf("STANDBY ");
wait(10);
state = STATE_START;
}
else if ( state == STATE_START )
{
printf("START ");
wait(20);
state = STATE_RUN;
}
else if ( state == STATE_RUN )
{
printf("RUN ");
wait(30);
state = STATE_STOP;
}
else // ( state == STATE_STOP )
{
printf("STOP ");
wait(20);
state = STATE_STANDBY;
}
}
return 0;
}
而 constants.h 包含
#define LOOP_SIZE 10000000
#define MACHINE_LOOP 100
我考虑了三种变体来定义状态常量。上面的宏,枚举:
enum {
STATE_STANDBY=0,
STATE_START,
STATE_RUN,
STATE_STOP
} possible_states;
和 const
:
static const int STATE_STANDBY = 0;
static const int STATE_START = 1;
static const int STATE_RUN = 2;
static const int STATE_STOP = 3;
其余代码保持不变。
测试和结果
测试是在 64 位 linux 机器上进行的,并使用 gcc
编译
全局规模
gcc main.c -o main
给出宏:7310字节
枚举:7349 字节
常量:7501 字节gcc -O2 main.c -o main
给出宏:7262字节
枚举:7301 字节
常量:7262 字节gcc -Os main.c -o main
给出宏:7198字节
枚举:7237 字节
常量:7198 字节
打开优化后,const 和宏变体的大小相同。枚举总是稍大一些。使用 gcc -S
我可以看到不同之处在于 .comm 中的 possible_states,4,4
。所以枚举总是比宏大。 const 可以更大,但也可以优化掉。
部分大小
我使用 objdump -h main
检查了程序的几个部分:.text、.data、.rodata、.bss、.dynamic。在所有情况下,.bss 有 8 个字节,.data 有 16 个字节,.dynamic:480 个字节。
.rodata 有 31 个字节,除了未优化的 const 版本(47 个字节)。
.text 根据优化情况从 620 字节到 780 字节不等。 const unoptimised 是唯一一个具有相同标志的不同。
执行速度
我运行了程序几次,但我没有注意到不同版本之间的实质性差异。在没有优化的情况下,它运行了大约 50 秒。 -O2
缩短至 20 秒,-Os
缩短至 3 分钟以上。我用 /usr/bin/time
测量了时间。
内存使用情况
使用 time -f %M
,我在每种情况下得到大约 450k,当使用 valgrind --tool=massif --pages-as-heap=yes
在所有情况下我都会得到 6242304。
结论
每当激活一些优化时,唯一显着的区别是枚举情况多了大约 40 字节。但没有 RAM 或速度差异。
关于范围、可读性......个人偏好的其他争论仍然存在。
关于c - C : enum vs constant vs defines 中的模式设置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46365504/