我刚刚使用 Ivor Horton 的《Beginning C》一书回顾了一些 C 学习。我谈到了声明常量,这似乎与同一句话中的变量混淆了。
只是为了澄清一下,在 C 中指定常量和变量有什么区别,实际上,什么时候需要使用常量而不是变量?我知道人们说在程序执行期间信息没有改变时使用常量,但我真的想不出什么时候不能使用变量来代替。
正如您可以从名称中猜到的那样,变量会随着时间而变化。如果它没有变化,则“没有损失”。当您告诉编译器该值不会改变时,编译器可以进行一大堆优化,例如直接内联该值并且从不为堆栈上的常量分配任何空间。
然而,你不能总是指望你的编译器足够聪明,能够正确地确定一个值一旦设置就会改变。在编译器无法以 100% 的信心确定这一点的任何情况下,编译器都会在安全方面犯错并假设它可能会改变。这可能会导致各种性能影响,例如避免内联、不优化某些循环、创建对并行性不友好的目标代码。
正因为如此,并且由于可读性也很重要,所以您应该尽可能地使用显式常量,并将变量留给实际可以改变的东西。
至于为什么使用常量而不是文字数字:
1)它使代码更具可读性。每个人都知道 3.14 是什么(希望如此),并不是每个人都知道 3.07 是宾夕法尼亚州的所得税税率。这是特定领域知识的一个例子,并不是每个将来维护您的代码的人(例如,税务软件)都会知道它。
2)当您进行更改时,它可以节省工作量。如果将来税率发生变化,那么每 3.07 到 3.18 去换一次会很烦人。您总是希望最小化更改并理想地进行一次更改。您必须进行的并发更改越多,您忘记某些内容并导致错误的风险就越高。
3) 你避免了有风险的错误。假设有两个州的所得税税率为 3.05,然后其中一个变为 3.18,而另一个保持在 3.07。只是去替换,你最终可能会出现严重的错误。当然,许多整数或字符串常量值比“3.07”更常见。例如,数字 7 可以代表一周中的天数,以及其他的东西。在大型程序中,很难确定每个字面值的含义。
4) 在字符串文本的情况下,通常使用字符串的符号名称来允许字符串池在支持多种语言的情况下快速变化。
请注意,除了变量和“常量变量”之外,还有一些带有枚举的语言。枚举实际上允许您为一小组常量(例如,返回值)定义一个类型,因此使用它们将提供类型安全。
例如,如果我有一个星期和月份的枚举,如果我将一个月分配到一天,我会收到警告。如果我只使用整数常量,则将第 3 天分配给第 3 个月时不会发出警告。您总是需要类型安全,并且它提高了可读性。枚举也更适合定义顺序。想象一下,你有一周中的几天的常量,现在你希望你的一周从星期一而不是星期日开始。
使用常量更像是一种防御性编程方式,以保护自己免受自己的伤害,以免在凌晨 2 点或喝咖啡之前编码时意外更改代码中某处的值。
从技术上讲,是的,您可以改用变量。
与变量相比,常量有几个优点。
常量提供了某种程度的保证,即代码不能改变基础值。这对于一个较小的项目来说并不重要,但对于一个由多个作者编写的多个组件的大型项目来说很重要。
常量还为编译器提供了强有力的优化提示。由于编译器知道值不能改变,它不需要从内存中加载值,并且可以优化代码以仅针对常量的确切值工作(例如,编译器可以使用移位进行乘法/除法如果 const 是 2 的幂。)
常量本质上也是静态的——您可以在头文件中声明常量及其值,而不必担心将其定义在一个地方。
一方面,性能优化。
更重要的是,这是为人类读者准备的。请记住,您的目标受众不仅仅是编译器。它有助于在代码中表达自己,并避免注释。
const int spaceTimeDimensions = 4;
if(gpsSattelitesAvailable >= spaceTimeDimensions)
Good();
常量是当您只想共享内存时,它不会改变。
对于像 C 这样的低级语言,常量允许进行多种编译优化。
对于一般的编程语言,您并不真的需要它们。Ruby 和 JavaScript 等高级动态语言没有它们(或者至少在真正的常量意义上没有)。就像您建议的那样,使用变量代替。
const
关键字常用于函数参数,特别是指针,表示指针指向的内存不会被函数修改。以 declerationstrcpy
为例:
char *strcpy(char *dest, const char *src);
否则,例如,声明如
const int my_magic_no = 54321;
可能比:
#define MY_MAGIC_NO 54321
出于类型安全的原因。
这是捕获特定类别错误的一种非常简单的方法。如果你声明一个变量const
,并且不小心尝试修改它,编译器会调用它。
不使用 const 可能意味着团队项目中的某个人可以声明在哪里,并在其他团队成员的其他地方int FORTY_TWO = 42
使其相等。FORTY_TWO = 41
因此世界末日发生了,你也失去了生命的答案。const
尽管这一切都不会发生。与普通变量的存储相比, Plusconst
存储在内存中的其他位置,并且效率更高。