在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 };
当前回答
一个简单的区别:
在预处理时,常量被替换为它的值。 因此,不能将解引用操作符应用于定义,但可以将解引用操作符应用于变量。
如您所料,define比static const更快。
例如,有:
#define mymax 100
你不能做printf("address of constant is %p",&mymax);
但是有
const int mymax_var=100
你可以做printf("address of constant is %p",&mymax_var);
更清楚地说,define在预处理阶段被它的值替换,因此程序中没有存储任何变量。我们只有使用define的程序文本段的代码。
然而,对于static const,我们有一个被分配到某处的变量。对于gcc,静态const分配在程序的文本段中。
上面,我想讲的是引用操作符,所以用引用替换解引用。
其他回答
使用const而不是#define总是更好。这是因为const是由编译器处理的,而#define是由预处理器处理的。这就像#define本身不是代码的一部分(粗略地说)。
例子:
#define PI 3.1416
符号名称PI可能永远不会被编译器看到;它可能在源代码到达编译器之前被预处理器删除。因此,名称PI可能无法进入符号表。如果在编译过程中遇到涉及使用常量的错误,这可能会令人困惑,因为错误消息可能指向3.1416,而不是PI。如果圆周率定义在一个你没有写的头文件中,你就不知道3.1416是从哪里来的。
这个问题也可能在符号调试器中突然出现,因为您正在编程的名称可能不在符号表中。
解决方案:
const double PI = 3.1416; //or static const...
不要认为“哪个总是最好的”有一个答案,但是,正如马蒂厄所说
静态常量
类型安全。我对#define最大的不满是,在Visual Studio中调试时,你不能看到变量。它给出一个无法找到符号的错误。
顺便说一句,#define的另一个选择是“enum”,它提供了适当的作用域,但表现得像一个“真正的”常量。例如:
enum {number_ten = 10;}
在许多情况下,定义枚举类型并创建这些类型的变量是有用的;如果这样做了,调试器可能能够根据变量的枚举名称显示变量。
然而,这样做有一个重要的警告:在c++中,枚举类型与整数的兼容性有限。例如,默认情况下,不能对它们进行算术运算。我发现这是枚举的一个奇怪的默认行为;虽然有一个“严格的enum”类型会很好,但考虑到c++通常与C兼容,我认为“enum”类型的默认行为应该与整数互换。
我写了一个快速测试程序来证明其中的一个区别:
#include <stdio.h>
enum {ENUM_DEFINED=16};
enum {ENUM_DEFINED=32};
#define DEFINED_DEFINED 16
#define DEFINED_DEFINED 32
int main(int argc, char *argv[]) {
printf("%d, %d\n", DEFINED_DEFINED, ENUM_DEFINED);
return(0);
}
这个编译带有以下错误和警告:
main.c:6:7: error: redefinition of enumerator 'ENUM_DEFINED'
enum {ENUM_DEFINED=32};
^
main.c:5:7: note: previous definition is here
enum {ENUM_DEFINED=16};
^
main.c:9:9: warning: 'DEFINED_DEFINED' macro redefined [-Wmacro-redefined]
#define DEFINED_DEFINED 32
^
main.c:8:9: note: previous definition is here
#define DEFINED_DEFINED 16
^
注意,当define给出警告时,enum给出一个错误。
如果你有mystruct.var这样的东西,#define var 5会给你带来麻烦。
例如,
struct mystruct {
int var;
};
#define var 5
int main() {
struct mystruct foo;
foo.var = 1;
return 0;
}
预处理器将取代它,代码将无法编译。因此,传统的编码风格建议所有常量#定义都使用大写字母以避免冲突。