我是否更喜欢常量而不是定义?

hel*_*hod 46 c const c-preprocessor

在C中,我是否更喜欢常量而不是定义?我最近阅读了很多代码,所有的例子都大量使用了定义.

AnT*_*AnT 101

不,通常你不应该在C中使用const限定对象来创建名称常量.要在C中创建命名常量,您应该使用宏(#define)或枚举.事实上,C语言没有常数,从某种意义上说,你似乎暗示着.(在这方面,C与C++有很大不同)

在C语言中,常量常量表达式的概念与C++的定义截然不同.在C 常量中表示字面值,如123.以下是C 中常量的一些示例

123
34.58
'x'
Run Code Online (Sandbox Code Playgroud)

C中的常量可用于构建常量表达式.但是,由于任何类型的const限定对象都不是C中的常量,因此它们不能用于常量表达式,因此,您不能使用需要常量表达式的const限定对象.

例如,以下不是常数

const int C = 123; /* C is not a constant!!! */
Run Code Online (Sandbox Code Playgroud)

由于以上C不是常量,因此不能用于在文件范围内声明数组类型

typedef int TArray[C]; /* ERROR: constant expression required */
Run Code Online (Sandbox Code Playgroud)

它不能用作案例标签

switch (i) {
  case C: ; /* ERROR: constant expression required */
}
Run Code Online (Sandbox Code Playgroud)

它不能用作位域宽度

struct S {
  int f : C; /* ERROR: constant expression required */
};
Run Code Online (Sandbox Code Playgroud)

它不能用作具有静态存储持续时间的对象的初始化程序

static int i = C; /* ERROR: constant expression required */
Run Code Online (Sandbox Code Playgroud)

它不能用作枚举初始值设定项

enum {
  E = C /* ERROR: constant expression required */
};
Run Code Online (Sandbox Code Playgroud)

即它不能用于需要常数的任何地方.

这可能看似违反直觉,但这就是C语言的定义方式.

这就是您#define在使用的代码中看到这些众多-s的原因.同样,在C语言中,const-qualified对象的使用非常有限.它们基本上完全没用作"常量",这就是为什么在C语言中你基本上被迫使用#define或枚举来声明真正的常量.

当然,在const限定对象为您工作的情况下,即它完成您希望它做的事情,它确实在很多方面优于宏,因为它是作用域和键入的.在适用的情况下,您可能更喜欢这些对象,但在一般情况下,您必须考虑上述限制.

  • +1用于理解和正确表达C/C++的差异,这一点似乎在许多人身上丢失了. (18认同)
  • @Helper方法:你可以.但这仍然使它们成为VLA('V'代表"变量"),这使它们与普通数组完全不同.它们仅允许在允许VLA的情况下使用.即使在C99中,上面的typedef也不会编译.具有静态存储持续时间的数组将不会使用大小这样的"常量"进行编译.结构成员数组也不会编译.等等. (2认同)

Leo*_*Hat 10

常数应优先于defines.有几个优点:

  • 类型安全.虽然C是一种弱类型的语言,但是使用了define丢失所有类型的安全性,这将允许编译器为您挑选问题.

  • 易于调试.您可以通过调试器更改常量的值,而defines由代码中的预处理器自动更改为实际值,这意味着如果要更改测试/调试的值,则需要重新编译.

  • 我发现很多编译器会将`const static ints'加到立即的操作码常量中,就像#defines一样,这使得它们也无法在调试器中进行更改. (2认同)

小智 7

也许我一直在使用它们,但至少在gcc中,你不能在case语句中使用常量.

const int A=12;
switch (argc) {
    case A:
    break;
}
Run Code Online (Sandbox Code Playgroud)


Laz*_*zer 6

虽然这个问题是针对C的,但我想知道这个很好:

#include<stdio.h>
int main() {
    const int CON = 123;
    int* A = &CON;
    (*A)++;
    printf("%d\n", CON);  // 124 in C
}
Run Code Online (Sandbox Code Playgroud)

适用于C语言,但不适用于C++语言

使用的一个原因#define是避免这样的事情弄乱你的代码,特别是它是C和C++的混合.


asv*_*kau 5

很多人在这里给你提供"C++风格"的建议.有些人甚至说C++参数适用于C.这可能是一个公平的观点.(无论是否感觉有点主观.)const有时说意味着两种语言不同的人也是正确的.

但这些都是小问题而且个人而言,我认为事实上,无论采取哪种方式都会产生相对较小的后果.这是一个风格问题,我认为不同的人群会给你不同的答案.

在常见用法,历史用法和最常见的风格方面,在C中,它更常见#define.在C代码中使用C++主义对C编码器的某个狭窄部分来说可能很奇怪.(包括我,这就是我的偏见所在.)

但我很惊讶没有人提出一个中间解决方案,在两种语言中"感觉正确":如果它适合一组整数常量,请使用enum.