在C中的以下陈述中哪一个更好用?
static const int var = 5;
要么
#define var 5
要么
enum { var = 5 };
Jonathan Lef.. 660
这取决于你需要的价值.你(和其他人到目前为止)省略了第三种选择:
static const int var = 5;
#define var 5
enum { var = 5 };
忽略有关名称选择的问题,然后:
如果需要传递指针,则必须使用(1).
因为(2)显然是一个选项,所以你不需要传递指针.
(1)和(3)都在调试器的符号表中有一个符号 - 这使得调试更容易.(2)更有可能没有符号,让你想知道它是什么.
(1)不能用作全局范围内数组的维度; (2)和(3)都可以.
(1)不能在函数范围内用作静态数组的维数; (2)和(3)都可以.
在C99下,所有这些都可以用于本地阵列.从技术上讲,使用(1)意味着使用VLA(可变长度数组),尽管'var'引用的维度当然会固定为5.
(1)不能在switch语句之类的地方使用; (2)和(3)都可以.
(1)不能用于初始化静态变量; (2)和(3)都可以.
(2)可以更改您不想更改的代码,因为它由预处理器使用; (1)和(3)都不会产生意想不到的副作用.
您可以检测是否已在预处理器中设置了(2); (1)和(3)都不允许这样做.
因此,在大多数情况下,更喜欢"枚举"而非替代品.否则,第一个和最后一个要点可能是控制因素 - 如果你需要同时满足这两个要点,你必须更加努力.
如果你问的是C++,那么你每次都会使用选项(1) - 静态const.
这取决于你需要的价值.你(和其他人到目前为止)省略了第三种选择:
static const int var = 5;
#define var 5
enum { var = 5 };
忽略有关名称选择的问题,然后:
如果需要传递指针,则必须使用(1).
因为(2)显然是一个选项,所以你不需要传递指针.
(1)和(3)都在调试器的符号表中有一个符号 - 这使得调试更容易.(2)更有可能没有符号,让你想知道它是什么.
(1)不能用作全局范围内数组的维度; (2)和(3)都可以.
(1)不能在函数范围内用作静态数组的维数; (2)和(3)都可以.
在C99下,所有这些都可以用于本地阵列.从技术上讲,使用(1)意味着使用VLA(可变长度数组),尽管'var'引用的维度当然会固定为5.
(1)不能在switch语句之类的地方使用; (2)和(3)都可以.
(1)不能用于初始化静态变量; (2)和(3)都可以.
(2)可以更改您不想更改的代码,因为它由预处理器使用; (1)和(3)都不会产生意想不到的副作用.
您可以检测是否已在预处理器中设置了(2); (1)和(3)都不允许这样做.
因此,在大多数情况下,更喜欢"枚举"而非替代品.否则,第一个和最后一个要点可能是控制因素 - 如果你需要同时满足这两个要点,你必须更加努力.
如果你问的是C++,那么你每次都会使用选项(1) - 静态const.
一般来说:
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_ ),在阅读库时,您会注意到(通常)后面跟着特定区域(库)的名称,然后是一个有意义的名称.
它通常会使冗长的名字:)
在C中,特别是?在C中,正确答案是:使用#define
(或者,如果适用enum
)
虽然具有对象的作用域和键入属性是有益的,但const
实际上const
C 中的对象(与C++相反)不是真正的常量,因此在大多数实际情况下通常是无用的.
因此,在C中,选择应取决于您计划如何使用常量.例如,您不能将const int
对象用作case
标签(宏将起作用).您不能将const int
对象用作位字段宽度(而宏将起作用).在C89/90中,您不能使用const
对象来指定数组大小(宏将起作用).即使在C99中,const
当您需要非VLA阵列时,也无法使用对象指定数组大小.
如果这对您很重要,那么它将决定您的选择.大多数时候,你别无选择,只能#define
在C中使用.不要忘记另一种选择,它会在C中产生真正的常量enum
.
在C++中,const
对象是真正的常量,所以在C++中,最好更喜欢const
变体(static
尽管不需要在C++中显式).
static const
和之间的区别在于#define
前者使用内存而后者不使用内存进行存储.其次,你不能传递一个地址,#define
而你可以传递一个地址static const
.实际上,这取决于我们所处的环境,我们需要从这两者中选择一个.在不同情况下,两者都处于最佳状态.请不要认为一个比另一个好...... :-)
如果情况确实如此,丹尼斯·里奇 本来会保持最好的一个......哈哈哈...... :-)
在C #define
中更受欢迎.您可以使用这些值来声明数组大小,例如:
#define MAXLEN 5 void foo(void) { int bar[MAXLEN]; }
static const
据我所知,ANSI C不允许您在此上下文中使用s.在C++中,您应该避免在这些情况下使用宏.你可以写
const int maxlen = 5; void foo() { int bar[maxlen]; }
static
因为内部链接已经暗示const
[仅限C++] ,所以甚至会遗漏.
const
C中的另一个缺点是你不能在初始化另一个时使用该值const
.
static int const NUMBER_OF_FINGERS_PER_HAND = 5; static int const NUMBER_OF_HANDS = 2; // initializer element is not constant, this does not work. static int const NUMBER_OF_FINGERS = NUMBER_OF_FINGERS_PER_HAND * NUMBER_OF_HANDS;
即使这不适用于const,因为编译器不会将其视为常量:
static uint8_t const ARRAY_SIZE = 16; static int8_t const lookup_table[ARRAY_SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; // ARRAY_SIZE not a constant!
我很乐意const
在这些情况下使用打字,否则......
如果你能逃脱它,static const
有很多优点.它遵循正常的范围原则,在调试器中可见,并且通常遵循变量服从的规则.
但是,至少在最初的C标准中,它实际上并不是一个常数.如果你使用#define var 5
,你可以写int foo[var];
一个声明,但你不能这样做(除了作为编译器扩展"with static const int var = 5;
.在C++中不是这种情况,static const
版本可以在版本可以使用的任何地方使用#define
,我相信这C99也是如此.
但是,永远不要#define
用小写名称命名常量.在翻译单元结束之前,它将覆盖对该名称的任何可能使用.宏常量应该在它们自己的命名空间中,它通常都是大写字母,可能带有前缀.
始终最好使用const而不是#define.这是因为const由编译器处理,而#define由预处理器处理.就像#define本身不是代码的一部分(粗略地说).
例:
#define PI 3.1416
编译器可能永远不会看到符号名称PI; 在源代码甚至到达编译器之前,它可能被预处理器删除.因此,名称PI可能无法输入到符号表中.如果在编译期间出现涉及使用常量的错误,则可能会造成混淆,因为错误消息可能指的是3.1416,而不是PI.如果在你没有写的头文件中定义PI,你就不知道3.1416来自哪里.
此问题也可能出现在符号调试器中,因为您编程的名称可能不在符号表中.
解:
const double PI = 3.1416; //or static const...
#define var 5
如果你有类似的东西,会给你带来麻烦mystruct.var
.
例如,
struct mystruct { int var; }; #define var 5 int main() { struct mystruct foo; foo.var = 1; return 0; }
预处理器将替换它,代码将无法编译.出于这个原因,传统的编码风格表明所有常量都#define
使用大写字母来避免冲突.
我写了快速测试程序来证明一个区别:
#includeenum {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给出警告时,枚举会给出错误.