在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而不是#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中调试时,你不能看到变量。它给出一个无法找到符号的错误。

我写了一个快速测试程序来证明其中的一个区别:

#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给出一个错误。

一般来说:

static const

因为它尊重作用域并且是类型安全的。

我能看到的唯一警告是:如果您希望变量可能在命令行上定义。还有另一种选择:

#ifdef VAR // Very bad name, not long enough, too general, etc..
  static int const var = VAR;
#else
  static int const var = 5; // default value
#endif

尽可能使用类型安全的替代方法,而不是宏/省略号。

如果你真的需要使用宏(例如,你想要__FILE__或__LINE__),那么你最好非常小心地命名你的宏:在它的命名约定中,Boost推荐所有大写字母,以项目的名称(这里是BOOST_)开头,而仔细阅读库,你会注意到这(通常)后面是特定区域(库)的名称,然后是一个有意义的名称。

它通常会产生很长的名字:)

如果你可以使用它,静态const有很多优点。它遵循正常的作用域原则,在调试器中可见,并且通常遵守变量所遵循的规则。

然而,至少在最初的C标准中,它实际上不是一个常数。如果你使用#define var 5,你可以写int foo[var];作为一个声明,但你不能这样做(除非作为一个编译器扩展“与静态const int var = 5;;在c++中不是这样,静态const版本可以在#define版本可以使用的任何地方使用,我相信C99也是如此。

但是,永远不要用小写名称命名#define常量。它将覆盖该名称的任何可能使用,直到翻译单元结束。宏常量应该在实际上属于它们自己的名称空间中,传统上都是大写字母,可能还有一个前缀。