我应该比常量更喜欢定义?

在C中,我更喜欢常量超过了定义吗? 我最近阅读了很多代码,所有的例子都大量使用了定义。

不,一般来说,你不应该在C中使用const限定的对象来创build名称常量。 为了在C中创build一个命名常量 ,你应该使用macros( #define )或枚举。 事实上,C语言没有常数,从某种意义上说,你似乎暗示。 (在这方面C与C ++明显不同)

在C语言中, 常量常量expression式的概念与C ++的定义非常不同。 在C 常数意味着一个文字值 ,如123 。 下面是C中常量的一些例子

 123 34.58 'x' 

C中的常量可以用来build立常量expression式 。 但是,由于任何types的const限定对象都不是C中的常量 ,所以它们不能用于常量expression式中,因此,不能使用需要常量expression式的const限定对象。

例如,以下不是一个常数

 const int C = 123; /* C is not a constant!!! */ 

由于上面的C不是常量,所以不能用于在文件范围内声明数组types

 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 */ }; 

即不能在需要常量的地方使用。

这看起来可能与直觉相反,但是这就是语言的定义。

这就是为什么你在你正在使用的代码中看到许多#define -s。 再次,在C语言中,const限定对象的使用非常有限。 它们基本上完全没用“常量”,这就是为什么在C语言中你基本上被迫使用#define或枚举来声明真正的常量。

当然,在一个const限定对象适用于你的情况下,也就是说它做你想做的事,在许多方面它确实优于macros,因为它是作用域和types的。 在适用的情况下,您应该更喜欢这样的对象,但是一般情况下您必须考虑到上述限制。

常量应该优于define s。 有几个优点:

  • types安全 。 虽然C是一种弱types的语言,但是使用一个define会失去所有的types安全性,这将使编译器为你挑选问题。

  • 易于debugging 。 您可以通过debugging器更改常量的值 ,而define s由代码自动在预处理器中更改为实际值,这意味着如果要更改testing/debugging值的值,编译。

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

 const int A=12; switch (argc) { case A: break; } 

这里有很多人给你“C ++风格”的build议。 有人甚至说C ++的论点适用于C.这可能是一个公平的观点。 (不pipe是不是感觉都是主观的)。说const的人有时候意味着两种语言不同的东西也是正确的。

但是这些大部分都是次要的,而且我个人认为,实际上这两种方式都有一个相对较小的结果。 这是一个风格问题,我认为不同的人会给你不同的答案。

在C中常见用法,历史用法和最常见的风格方面,看到#define更为典型。 在C代码中使用C ++ isms对于C代码的某个狭窄部分来说可能会变得很奇怪。 (包括我,所以这是我的偏见所在。)

但是我很惊讶,没有人提出一个中间的解决scheme,这两种语言都是“正确的”:如果它符合一组整数常量,就使用一个enum

虽然这个问题是针对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 ++的混合。

define可以用于很多目的(非常松散),如果你可以用const来替代它,const定义了一个variables,你可以用它来做更多的事情。

在下面的情况下,必须使用define

  • 指令开关
  • replace到您的源代码行
  • 代码macros

一个你必须使用define over const的例子是,如果你的版本号是3,而你希望版本4包含一些在版本3中不可用的方法

 #define VERSION 4 ... #if VERSION==4 ................ #endif 

定义是比常量更长的语言的一部分,所以很多旧的代码将使用它们,因为定义了代码写入时完成作业的唯一方法。 对于更新的代码,它可能只是程序员习惯的一个问题。

常量有一个types和一个值,所以当你的值有一个types时,它们会是首选的,但是当它是无types的(或多态的)时,它们将是首选的。

如果它不是以编程方式确定的,我使用#define 。 例如,如果我希望所有的UI对象之间有相同的空间,我可以使用#define kGUISpace 20

除了AndreyT在“C”代码中使用DEFINES而不是常量的绝好理由之外,还有另一个使用DEFINES的更实用的理由。

定义很容易定义和使用(.h)头文件,这是任何经验丰富的C编码器会期望find定义的常量。 在头文件中定义常量不是那么容易 – 它的代码更多,以避免重复的定义等

此外,“types安全”的参数是模拟大多数编译器会挑起一个明显的错误,例如将string赋值为int,或者将“做正确的事情”,如一个轻微的不匹配,如分配一个整数的浮动。

macros(定义)可以被预处理器使用,并且在编译时,常量不能。

您可以进行编译时检查以确保macros在有效范围内(如果不是,则#error或#fatal)。 如果尚未定义macros,可以使用默认值。 您可以使用数组大小​​的macros。

编译器可以使用macros进行优化,而不是使用常量进行优化:

 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 

我的大部分工作都是使用embedded式处理器,而没有出色的优化编译器。 也许海湾合作委员会会把SIZE_A当作一个macros来处理,在一些优化级别上。