C中的模式设置:枚举vs常量vs定义
我读了一些关于这个话题的问题:C中的模式设置:枚举vs常量vs定义,c,enums,embedded,C,Enums,Embedded,我读了一些关于这个话题的问题: 我知道,为了更好地封装和/或可读性,enum通常是#define宏的首选。此外,它还允许编译器检查类型以防止出现某些错误 const声明介于两者之间,允许类型检查和封装,但更为混乱 现在我在内存空间非常有限的嵌入式应用程序中工作(我们常常不得不为节省字节而斗争)。我的第一个想法是常数比枚举占用更多内存。但我意识到,我不确定常量将如何出现在最终固件中 例如: enum { standby, starting, active, stoping } s
#define
宏的首选。此外,它还允许编译器检查类型以防止出现某些错误
const
声明介于两者之间,允许类型检查和封装,但更为混乱
现在我在内存空间非常有限的嵌入式应用程序中工作(我们常常不得不为节省字节而斗争)。我的第一个想法是常数比枚举占用更多内存。但我意识到,我不确定常量将如何出现在最终固件中
例如:
enum { standby, starting, active, stoping } state;
问题: 在资源有限的环境中,
enum
vs#如何定义
vsstatic const
在执行速度和内存印记方面进行比较
我知道,为了更好地封装和/或可读性,enum通常是#define宏的首选
首选枚举主要是为了更好的可读性,但也因为它们可以在本地范围内声明,并且它们增加了一点点类型安全性(特别是在使用静态分析工具时)
常量声明介于类型检查和封装之间,但更为混乱
不完全是,这取决于范围。“全局”常量可能很混乱,但它们不像全局读/写变量那样糟糕,在某些情况下是合理的。与其他形式相比,const
的一个主要优点是,这类变量往往在.rodata
中分配,您可以使用调试器查看它们,这在宏和枚举中并不总是可行的(取决于调试器的性能)
请注意,#define
始终是全局的,enum
可能是也可能不是
我的第一个想法是常数比枚举占用更多内存
这是不正确的enum
变量通常是int
类型,尽管它们可以是较小的类型(因为它们的大小可能不同,所以不利于移植)。然而,枚举常量(即枚举声明中的内容)总是int
,这是一种至少16位的类型
另一方面,const
与您声明的类型一样大。因此,如果需要节省内存,const
优于enum
在资源有限的环境中,enum与#define与static const在执行速度和内存印记方面如何比较
执行速度可能不会有什么不同——这是不可能说的,因为它是特定于系统的。然而,由于枚举往往会给出16位或更大的值,因此在需要节省内存时,它们是一个坏主意。如果你需要一个精确的内存布局,它们也是一个坏主意,这在嵌入式系统中是很常见的。当然,编译器可能会将它们优化到更小的大小
其他建议:
- 在嵌入式系统中始终使用
类型,特别是当您需要精确的内存布局时李>stdint.h
- 枚举很好,除非您需要它们作为某些内存布局(如数据协议)的一部分。不要在这种情况下使用枚举
在需要将某些内容存储在闪存中时非常理想。这些变量有自己的地址,更容易调试const
- 在嵌入式系统中,为了减小闪存大小而优化代码通常没有多大意义,而是为了减小RAM大小而进行优化。
将始终在.text闪存中结束,而enum和const可能在RAM、#define
闪存或.rodata
闪存中结束
- 当在嵌入式系统上优化大小(RAM或flash)时,请跟踪映射文件(链接器输出文件)中的变量,并查找突出的内容,而不是一时兴起地到处跑,手动优化随机内容。通过这种方式,您还可以检测一些应该是
的变量是否错误地在RAM中结束(错误)const
#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;