在C语言中,下列语句中使用哪个更好?
static const int var = 5;
or
#define var 5
or
enum { var = 5 };
在C语言中,下列语句中使用哪个更好?
static const int var = 5;
or
#define var 5
or
enum { var = 5 };
当前回答
的定义
const int const_value = 5;
并不总是定义一个常数值。一些编译器(例如tcc 0.9.26)只分配名称为“const_value”的内存。使用标识符“const_value”你不能修改这个内存。但是你仍然可以使用另一个标识符来修改内存:
const int const_value = 5;
int *mutable_value = (int*) &const_value;
*mutable_value = 3;
printf("%i", const_value); // The output may be 5 or 3, depending on the compiler.
这意味着定义
#define CONST_VALUE 5
是定义一个不能用任何方法修改的常数值的唯一方法。
其他回答
如果你可以使用它,静态const有很多优点。它遵循正常的作用域原则,在调试器中可见,并且通常遵守变量所遵循的规则。
然而,至少在最初的C标准中,它实际上不是一个常数。如果你使用#define var 5,你可以写int foo[var];作为一个声明,但你不能这样做(除非作为一个编译器扩展“与静态const int var = 5;;在c++中不是这样,静态const版本可以在#define版本可以使用的任何地方使用,我相信C99也是如此。
但是,永远不要用小写名称命名#define常量。它将覆盖该名称的任何可能使用,直到翻译单元结束。宏常量应该在实际上属于它们自己的名称空间中,传统上都是大写字母,可能还有一个前缀。
在C语言中?在C语言中,正确的答案是:使用#define(或者,如果合适,使用enum)
虽然具有const对象的作用域和类型属性是有益的,但实际上C中的const对象(与c++相反)并不是真正的常量,因此在大多数实际情况下通常是无用的。
所以,在C语言中,选择应该取决于你计划如何使用常数。例如,你不能使用const int对象作为case标签(而宏可以)。你不能使用const int对象作为位域宽度(而宏可以)。在C89/90中,你不能使用const对象来指定数组大小(而宏可以)。即使在C99中,当你需要一个非vla数组时,你也不能使用const对象来指定数组大小。
如果这对你很重要,那么它将决定你的选择。大多数时候,你别无选择,只能在C中使用#define。不要忘记另一个选择,它在C - enum中产生真正的常量。
在c++中,const对象是真正的常量,所以在c++中,最好使用const变体(但在c++中不需要显式的静态)。
虽然这个问题是关于整数的,但值得注意的是,如果需要常量结构或字符串,#define和enum是无用的。它们通常都作为指针传递给函数。(对于字符串,它是必需的;有了结构,效率就高多了。)
As for integers, if you're in an embedded environment with very limited memory, you might need to worry about where the constant is stored and how accesses to it are compiled. The compiler might add two consts at run time, but add two #defines at compile time. A #define constant may be converted into one or more MOV [immediate] instructions, which means the constant is effectively stored in program memory. A const constant will be stored in the .const section in data memory. In systems with a Harvard architecture, there could be differences in performance and memory usage, although they'd likely be small. They might matter for hard-core optimization of inner loops.
这取决于你需要这个值做什么。你(和目前所有人一样)忽略了第三种选择:
Static const int var = 5; #定义var 5 枚举{var = 5};
忽略名字的选择问题,那么:
If you need to pass a pointer around, you must use (1). Since (2) is apparently an option, you don't need to pass pointers around. Both (1) and (3) have a symbol in the debugger's symbol table - that makes debugging easier. It is more likely that (2) will not have a symbol, leaving you wondering what it is. (1) cannot be used as a dimension for arrays at global scope; both (2) and (3) can. (1) cannot be used as a dimension for static arrays at function scope; both (2) and (3) can. Under C99, all of these can be used for local arrays. Technically, using (1) would imply the use of a VLA (variable-length array), though the dimension referenced by 'var' would of course be fixed at size 5. (1) cannot be used in places like switch statements; both (2) and (3) can. (1) cannot be used to initialize static variables; both (2) and (3) can. (2) can change code that you didn't want changed because it is used by the preprocessor; both (1) and (3) will not have unexpected side-effects like that. You can detect whether (2) has been set in the preprocessor; neither (1) nor (3) allows that.
因此,在大多数情况下,优先选择“enum”而不是其他选项。否则,第一个和最后一个要点很可能是控制因素——如果你需要同时满足这两个点,你必须更努力地思考。
如果你问的是c++,那么你每次都应该使用option (1) - static const。
顺便说一句,#define的另一个选择是“enum”,它提供了适当的作用域,但表现得像一个“真正的”常量。例如:
enum {number_ten = 10;}
在许多情况下,定义枚举类型并创建这些类型的变量是有用的;如果这样做了,调试器可能能够根据变量的枚举名称显示变量。
然而,这样做有一个重要的警告:在c++中,枚举类型与整数的兼容性有限。例如,默认情况下,不能对它们进行算术运算。我发现这是枚举的一个奇怪的默认行为;虽然有一个“严格的enum”类型会很好,但考虑到c++通常与C兼容,我认为“enum”类型的默认行为应该与整数互换。