C &引用;“静态常数”;vs"#定义;vs";“枚举”;
在C语言的下列语句中,哪一个更适合使用C &引用;“静态常数”;vs"#定义;vs";“枚举”;,c,constants,C,Constants,在C语言的下列语句中,哪一个更适合使用 static const int var = 5; 或 或 一般来说: static const 因为它尊重范围并且是类型安全的 我能看到的唯一警告是:如果您希望在命令行上定义变量。还有一种选择: #ifdef VAR // Very bad name, not long enough, too general, etc.. static int const var = VAR; #else static int const var = 5;
static const int var = 5;
或
或
一般来说:
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
尽可能使用类型安全选项,而不是宏/省略号
如果您真的需要使用宏(例如,您想要\uuuuuu文件\uuuuuuu
或\uuuuuuu行\uuuuuuuu
),那么您最好非常小心地命名宏:在它的建议中,以项目名称开头(此处为BOOST),在仔细阅读库时,您会注意到这是(通常)后跟特定区域(库)的名称,然后使用有意义的名称
它通常会产生冗长的名称:)不要认为“哪一个总是最好的”是有答案的,但正如马修所说
静态常数
是类型安全的。不过,我对#define
最恼火的地方是在中调试时无法查看变量。它给出了一个找不到符号的错误。在C中,define
更受欢迎。您可以使用这些值来声明数组大小,例如:
#define MAXLEN 5
void foo(void) {
int bar[MAXLEN];
}
enum {number_ten = 10;}
据我所知,ANSI C不允许在此上下文中使用static const
s。在C++中,在这些情况下应该避免宏。你可以写
const int maxlen = 5;
void foo() {
int bar[maxlen];
}
甚至忽略了代码>静态< /代码>,因为内部链接由<代码> const <代码> > [C++中只有]。在C中,正确答案是:使用
#define
(或者,如果合适,使用enum
)
虽然拥有const
对象的作用域和类型属性是有益的,但实际上,C中的const
对象(与C++相反)不是真正的常量,因此在大多数实际情况下通常是无用的
因此,在C中,选择应该由您计划如何使用常量来决定。例如,不能将const int
对象用作大小写
标签(而宏可以工作)。不能将const int
对象用作位字段宽度(而宏可以工作)。在C89/90中,不能使用const
对象指定数组大小(而宏可以工作)。即使在C99中,当需要非数组时,也不能使用const
对象来指定数组大小
如果这对你很重要,那么它将决定你的选择。大多数情况下,您别无选择,只能在C中使用#define
。不要忘记另一种选择,即在C-enum
中生成真正的常量
<> > C++中的代码> const 对象是真的常量,所以在C++中,最好是选择< <代码> const 变体(不需要在C++中显式<代码>静态< /代码>)。 如果你能逃脱它,
#define var 5
,则可以编写int foo[var]作为一个声明,但您不能这样做(除了编译器扩展名),代码<静态const int var=5;< />代码>,C++中没有这种情况,其中<代码>静态const <代码>版本可以在任何地方使用<代码>定义< /COD>版本CAN,并且我相信这也是C99 ./P>的情况。
但是,切勿使用小写名称命名#定义常量。在翻译单元结束之前,它将覆盖该名称的任何可能使用。宏常量应位于其自己的名称空间中,通常都是大写字母,可能带有前缀。这取决于您需要的值f或者,您(以及目前为止的其他所有人)忽略了第三种选择:
#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
static const int var=5;
#定义变量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)-静态常量-每次。静态常量和定义的区别在于前者使用内存,后者不使用内存存储。其次,您不能传递定义的地址,而可以传递静态的地址
enum {number_ten = 10;}
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;
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!
struct mystruct {
int var;
};
#define var 5
int main() {
struct mystruct foo;
foo.var = 1;
return 0;
}
const int const_value = 5;
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
#define mymax 100
const int mymax_var=100
#define PI 3.1416
const double PI = 3.1416; //or static const...
#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
^