c - C : enum vs constant vs defines 中的模式设置

标签 c enums embedded

我已经阅读了关于该主题的几个问题:

而且我知道在 #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/

相关文章:

c - 从 C 中的文本文件中解析值

ios - 如何使枚举可编码?

database - 数据库字段中的枚举存储

ios - 方法是否可能(或建议)识别其调用方?

embedded - 可以重新编程键盘吗?

python - 专门为涉及线程和图形的项目研究 Python

c++ - 为什么运行时库是编译器选项而不是链接器选项?

c - KAA 无法创建 kaa_configuration_manager_set_root_receiver

embedded - 使用SPI初始化SD卡

c - 添加具有正确类型的节点 ID 的结构