在C语言中,以下哪个语句更好使用?
static const int var = 5;
或者#define var 5
或者enum { var = 5 };
在C语言中,以下哪个语句更好使用?
static const int var = 5;
或者#define var 5
或者enum { var = 5 };
static const int var = 5;
#define var 5
enum { var = 5 };
如果您在问有关C ++的问题,那么每次都应使用选项(1) - 静态常量。
enum
)的一个缺点是它们被实现为“整型”([C99] 6.7.2.2/3)。使用 #define
可以指定无符号和长整型,使用 U
和 L
后缀,而使用 const
则可以指定类型。enum
可能会导致常规类型转换方面的问题。 - Gauthierenum
和#define
本身并没有使用额外的空间。该值将出现在目标代码中作为指令的一部分,而不是分配存储在数据段、堆或栈上。对于static const int
,你会分配一些空间,但如果你不获取地址,编译器可能会对其进行优化。 - Jonathan Lefflerenum
(枚举类型)和static const
(静态常量):它们的值不能被修改。使用#define
定义的值可以通过#undefine
取消定义,而enum
和static const
的值则固定为给定的值。 - Daan Timmer一般来说:
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_)开头,然后在浏览库时,您会注意到这通常后跟着特定领域(库)的名称,然后是一个有意义的名称。
一般来说,它会导致名称很长 :)
extern const
来代替。 - Matthieu M.#if
可能比 #ifdef
更可取,但在这种情况下,如果要从命令行定义 var
为 0
,则使用 #if
将无法实现。因此,在这种情况下,只要 0
是 var
的合法值,使用 #ifdef
更有意义。 - Maartenconst int
对象是非法的。(当然,你的编译器可以支持它作为非标准的类似于C++的语言扩展)。 - AnT stands with Russiaconst
则表示只读。 const int r = rand();
是合法的。 - Keith Thompsonconst
相比,特别是与像array
或bitset
这样的stl
容器一起使用,最好使用constexpr
。 - Mayukh Sarkarswitch()
语句中进行测试,而不是在 case
中。我也刚刚被这个问题卡住了 ☺ - Hi-Angelstatic const
和#define
的区别在于前者使用内存,而后者不使用内存进行存储。其次,您不能传递#define
的地址,但可以传递static const
的地址。实际上,这取决于我们所处的情况,我们需要在这两者中选择一个。在不同的情况下,两者都能发挥最佳作用。请不要假设其中一个比另一个更好... :-)
如果是这种情况,Dennis Ritchie 就会保留最好的那个了... 哈哈哈... :-)
const
不再会占用内存。如果使用 -O3 选项编译代码,GCC(测试版本为4.5.3和一些较新版本)可以轻松地将 const int
优化为直接字面量。因此,如果您进行低RAM嵌入式开发(例如AVR),则可以安全地使用C中的常量,只要您使用GCC或其他兼容编译器即可。我没有测试过,但是我也预计Clang会做同样的事情。 - RaphaelC语言中,#define
更为流行。您可以使用这些值来声明数组大小,例如:
#define MAXLEN 5
void foo(void) {
int bar[MAXLEN];
}
据我所知,ANSI C不允许在这种情况下使用static const
,在C++中你应该避免使用宏。你可以写成:
const int maxlen = 5;
void foo() {
int bar[maxlen];
}
在C++中,由于const
已经隐含了内部链接,因此甚至可以省略static
。
const int MY_CONSTANT = 5;
,然后在另一个文件中使用extern const int MY_CONSTANT;
进行访问。我在标准(至少是C99)中没有找到有关于const
修改默认行为的任何信息,“6.2.2:5 如果对象的标识符的声明具有文件作用域且没有存储类说明符,则它的链接性是外部的”。 - Gauthierbar
是可变长度数组(VLA);编译器可能会生成代码,就好像它的长度是常量一样。 - Keith ThompsonC中使用const
的另一个缺点是无法在初始化另一个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 uint8_t const ARRAY_SIZE = 16;
突然不再编译可能有些具有挑战性,尤其是当#define ARRAY_SIZE 256
深埋在错综复杂的头文件之中时。那个全大写的名字ARRAY_SIZE
很容易引起麻烦。请将全部大写字母留给宏,并且永远不要定义不符合全部大写字母形式的宏。 - David Hammen--stc=c89
。第二个则不行,编译器会报错“可变数组”,因为ARRAY_SIZE是一个(只读)变量,而不是常量。 - Gauthierstatic
变量可以用于初始化其他static
变量。 - tstanislstatic const
有很多优点。它遵循正常的作用域原则,在调试器中可见,并且通常遵守变量所遵守的规则。#define var 5
,您可以编写int foo[var];
作为声明,但是您不能这样做(除非使用编译器扩展)static const int var = 5;
。在C++中不是这种情况,static const
版本可以在任何#define
版本可以使用的地方使用,我相信在C99中也是如此。#define
常量。它将覆盖该名称的任何可能使用,直到翻译单元结束。宏常量应该在实际上是它们自己的命名空间中,这通常是所有大写字母,也许带有前缀。const
仍不是真正的常数。你可以在C99中使用 const
声明数组大小,但这只是因为C99支持可变长度数组(VLA)。因此,它只能在允许使用VLA的情况下工作。例如,即使在C99中,您仍然无法使用 const
声明 struct
中成员数组的大小。 - AnT stands with Russiaconst int
大小来初始化数组,就像 C++ const 或宏一样。当然,你是否想依赖于 GCC 对标准的这种偏差取决于你自己,我个人会选择这种方式,除非你真的预见到将来会使用其他编译器,而 Clang 在这里也有相同的功能(测试版本为 Clang 3.7)。 - Raphael使用const比使用#define更好。这是因为编译器处理const,而预处理器处理#define。就像#define本身不是代码的一部分(粗略地说)。
例如:
#define 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
使用大写字母以避免冲突。#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
^