在C中,我是否更喜欢常量而不是定义?我最近阅读了很多代码,所有的例子都大量使用了定义。
答案 0 :(得分:100)
不,通常你不应该在C中使用const限定对象来创建名称常量。要在C中创建命名常量,您应该使用宏(#define
)或枚举。事实上,C语言没有常数,从某种意义上说,你似乎暗示着。 (在这方面,C与C ++显着不同)
在C语言中,常量和常量表达式的概念与C ++的定义截然不同。在C 常量中表示文字值,如123
。以下是C
123
34.58
'x'
C中的常量可用于构建常量表达式。但是,由于任何类型的const限定对象在C中都不是常量,因此它们不能在常量表达式中使用,因此,您不能使用需要常量表达式的const限定对象。
例如,以下不是常量
const int C = 123; /* C is not a constant!!! */
并且因为上面的C
不是常量,所以它不能用于在文件范围中声明数组类型
typedef int TArray[C]; /* ERROR: constant expression required */
不能用作案例标签
switch (i) {
case C: ; /* ERROR: constant expression required */
}
它不能用作位字段宽度
struct S {
int f : C; /* ERROR: constant expression required */
};
它不能用作具有静态存储持续时间
的对象的初始值设定项static int i = C; /* ERROR: constant expression required */
它不能用作枚举初始值设定项
enum {
E = C /* ERROR: constant expression required */
};
即不能在任何需要常量的地方使用。
这可能看似违反直觉,但这就是C语言的定义方式。
这就是为什么你在使用的代码中看到了这么多#define
- s的原因。同样,在C语言中,const-qualified对象的使用非常有限。它们基本上完全没用作“常量”,这就是为什么在C语言中你基本上被迫使用#define
或枚举来声明真正的常量。
当然,在const限定对象为你工作的情况下,即它做你想做的事情,它确实在很多方面优于宏,因为它是作用域和键入的。您可能应该在适用的情况下更喜欢这些对象,但在一般情况下,您必须考虑上述限制。
答案 1 :(得分:10)
常量应优先于define
s。有几个优点:
类型安全。虽然C是弱类型语言,但使用define
会失去所有类型的安全性,这将允许编译器为您解决问题。
易于调试。您可以通过调试器更改常量的值,而预处理器在代码中自动将define
更改为实际值,这意味着如果要更改测试/调试的值,则需要重新编译。
答案 2 :(得分:7)
也许我一直在使用它们,但至少在gcc中,你不能在case语句中使用常量。
const int A=12;
switch (argc) {
case A:
break;
}
答案 3 :(得分:6)
虽然这个问题是针对C的,但我想知道这个很好:
#include<stdio.h>
int main() {
const int CON = 123;
int* A = &CON;
(*A)++;
printf("%d\n", CON); // 124 in C
}
适用于 C ,但不适用于 C ++
使用#define
的一个原因是为了避免这些事情搞砸你的代码,特别是它是C和C ++的混合。
答案 4 :(得分:5)
这里的很多人都在给你“C ++风格”的建议。有些人甚至说C ++参数适用于C.这可能是一个公平的观点。 (无论是否感觉有点主观。)说const
的人有时意味着两种语言中不同的东西也是正确的。
但这些主要是小问题,而且我个人认为,实际上,无论采用哪种方式都会产生相对较小的后果。这是一个风格问题,我认为不同的人群会给你不同的答案。
就常见用法,历史用法和最常见的风格而言,在C中,看#define
更为典型。在C代码中使用C ++主义对C编码器的某个狭窄部分来说可能很奇怪。 (包括我,所以这就是我的偏见所在。)
但令我惊讶的是,没有人建议采用中间解决方案,在两种语言中“感觉正确”:如果它适合一组整数常量,请使用enum
。
答案 5 :(得分:3)
define可用于多种用途(非常松散),如果你可以用const替换它,应该避免使用const,它定义了一个变量,你可以用它做更多的事情。
在下面的情况下,必须使用define
您必须使用define over const的示例是当版本号为3并且您希望版本4包含某些在版本3中不可用的方法时
#define VERSION 4
...
#if VERSION==4
................
#endif
答案 6 :(得分:2)
定义语言的一部分比常量更长,所以很多旧代码都会使用它们,因为定义了编写代码时完成工作的唯一方法。对于最近的代码,它可能只是程序员习惯的问题。
常量有一个类型和一个值,所以当你的值有一个类型,而不是无类型(或多态)时,它们会是首选。
答案 7 :(得分:1)
如果它不是以编程方式确定的,我使用#define
。例如,如果我希望我的所有UI对象在它们之间具有相同的空格,我可以使用#define kGUISpace 20
。
答案 8 :(得分:1)
除了AndreyT使用DEFINES而不是“C”代码中常量的优秀理由外,使用DEFINES还有另外一个更实用的原因。
DEFINES很容易定义和使用(.h)头文件,这是任何有经验的C编码器期望找到定义的常量的地方。在头文件中定义consts并不是那么容易 - 它需要更多代码来避免重复定义等。
此外,“类型安全”参数没有实际意义,大多数编译器都会收到明显的错误,比如将字符串赋值给int,或者,在轻微不匹配时“做正确的事”,例如将一个整数赋给float。 / p>
答案 9 :(得分:1)
宏(定义)可以由预处理器使用,在编译时,常量不能。
您可以进行编译时检查以确保宏在有效范围内(如果不是,则为#error或#fatal)。如果宏尚未定义,则可以使用宏的默认值。您可以使用数组大小的宏。
编译器可以使用常量优化宏:
const int SIZE_A = 15;
#define SIZE_B 15
for (i = 0; i < SIZE_A + 1; ++i); // if not optimized may load A and add 1 on each pass
for (i = 0; i < SIZE_B + 1; ++i); // compiler will replace "SIZE_B + 1" with 16
我的大多数工作都是嵌入式处理器,没有出色的优化编译器。也许gcc会在一些优化级别上将SIZE_A视为宏。