Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的模式设置:枚举vs常量vs定义_C_Enums_Embedded - Fatal编程技术网

C中的模式设置:枚举vs常量vs定义

C中的模式设置:枚举vs常量vs定义,c,enums,embedded,C,Enums,Embedded,我读了一些关于这个话题的问题: 我知道,为了更好地封装和/或可读性,enum通常是#define宏的首选。此外,它还允许编译器检查类型以防止出现某些错误 const声明介于两者之间,允许类型检查和封装,但更为混乱 现在我在内存空间非常有限的嵌入式应用程序中工作(我们常常不得不为节省字节而斗争)。我的第一个想法是常数比枚举占用更多内存。但我意识到,我不确定常量将如何出现在最终固件中 例如: enum { standby, starting, active, stoping } s

我读了一些关于这个话题的问题:

我知道,为了更好地封装和/或可读性,enum通常是
#define
宏的首选。此外,它还允许编译器检查类型以防止出现某些错误

const
声明介于两者之间,允许类型检查和封装,但更为混乱

现在我在内存空间非常有限的嵌入式应用程序中工作(我们常常不得不为节省字节而斗争)。我的第一个想法是常数比枚举占用更多内存。但我意识到,我不确定常量将如何出现在最终固件中


例如:

enum { standby, starting, active, stoping } state;

问题: 在资源有限的环境中,
enum
vs
#如何定义
vs
static const
在执行速度和内存印记方面进行比较

我知道,为了更好地封装和/或可读性,enum通常是#define宏的首选

首选枚举主要是为了更好的可读性,但也因为它们可以在本地范围内声明,并且它们增加了一点点类型安全性(特别是在使用静态分析工具时)

常量声明介于类型检查和封装之间,但更为混乱

不完全是,这取决于范围。“全局”常量可能很混乱,但它们不像全局读/写变量那样糟糕,在某些情况下是合理的。与其他形式相比,
const
的一个主要优点是,这类变量往往在
.rodata
中分配,您可以使用调试器查看它们,这在宏和枚举中并不总是可行的(取决于调试器的性能)

请注意,
#define
始终是全局的,
enum
可能是也可能不是

我的第一个想法是常数比枚举占用更多内存

这是不正确的
enum
变量通常是
int
类型,尽管它们可以是较小的类型(因为它们的大小可能不同,所以不利于移植)。然而,枚举常量(即枚举声明中的内容)总是
int
,这是一种至少16位的类型

另一方面,
const
与您声明的类型一样大。因此,如果需要节省内存,
const
优于
enum

在资源有限的环境中,enum与#define与static const在执行速度和内存印记方面如何比较

执行速度可能不会有什么不同——这是不可能说的,因为它是特定于系统的。然而,由于枚举往往会给出16位或更大的值,因此在需要节省内存时,它们是一个坏主意。如果你需要一个精确的内存布局,它们也是一个坏主意,这在嵌入式系统中是很常见的。当然,编译器可能会将它们优化到更小的大小

其他建议:

  • 在嵌入式系统中始终使用
    stdint.h
    类型,特别是当您需要精确的内存布局时
  • 枚举很好,除非您需要它们作为某些内存布局(如数据协议)的一部分。不要在这种情况下使用枚举
  • const
    在需要将某些内容存储在闪存中时非常理想。这些变量有自己的地址,更容易调试
  • 在嵌入式系统中,为了减小闪存大小而优化代码通常没有多大意义,而是为了减小RAM大小而进行优化。
    #define
    将始终在.text闪存中结束,而enum和const可能在RAM、
    .rodata
    闪存或
    闪存中结束
  • 当在嵌入式系统上优化大小(RAM或flash)时,请跟踪映射文件(链接器输出文件)中的变量,并查找突出的内容,而不是一时兴起地到处跑,手动优化随机内容。通过这种方式,您还可以检测一些应该是
    const
    的变量是否错误地在RAM中结束(错误)

我使用了一个OpenGL库,它定义了枚举中的大多数常量,默认的OpenGL头将其定义为
#defines
。因此,作为标题/库的用户,没有太大的区别。这只是设计的一个方面。当使用纯C时,没有
静态常量
,除非它是一个变化的东西,或者是一个像
(extern)static const char[]version这样的大字符串。就我自己而言,我避免使用宏,因此在特殊情况下可以重用标识符。将C代码移植到C++时,枚举甚至是范围化的,并且是类型检查的。
特性:字符用法和可读性:

#define MY_CONST1 10
#define MY_CONST2 20
#define MY_CONST3 30
//...
#define MY_CONSTN N0
vs


为了得到一些实质性的答案,我做了一个简单的测试

代码 我写了一个简单的C程序main.C:

我考虑了三个变量来定义状态常数。如上所述的宏,枚举:

enum {
  STATE_STANDBY=0,
  STATE_START,
  STATE_RUN,
  STATE_STOP
} possible_states;
常量

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字节

启用优化时,常量和宏变量的大小相同。枚举总是稍大一些。使用
gcc-S
我可以看出差异是
可能的状态,4,4
in.comm。因此枚举总是大于宏。常数可以更大,但也可以优化
#define LOOP_SIZE     10000000
#define MACHINE_LOOP  100
enum {
  STATE_STANDBY=0,
  STATE_START,
  STATE_RUN,
  STATE_STOP
} possible_states;
static const int  STATE_STANDBY = 0;
static const int  STATE_START   = 1;
static const int  STATE_RUN     = 2;
static const int  STATE_STOP    = 3;
enum {
  STATE_STANDBY = 0,
  STATE_START,
  STATE_RUN,
  STATE_STOP
} possible_states;
// Define just the enumeration constants
enum { STATE_STANDBY, ... };

// Define the enumeration constants and the
// type "enum possible_states"
enum possible_states { STATE_STANDBY, ... };

// Define the enumeration constants and the
// type "possible_states"
typedef enum { STATE_STANDBY, ... } possible_states;