我最近重新学习了一些C语言,使用了Ivor Horton的《Beginning C》书籍。我遇到了关于声明常量的问题,似乎在同一句中与变量混淆了。
为了澄清,在C语言中指定常量和变量之间的区别是什么?实际上,你什么时候需要使用常量而不是变量呢?我知道有人说在程序执行期间信息不会改变时使用常量,但我真的想不出何时不能使用变量代替常量。
我最近重新学习了一些C语言,使用了Ivor Horton的《Beginning C》书籍。我遇到了关于声明常量的问题,似乎在同一句中与变量混淆了。
为了澄清,在C语言中指定常量和变量之间的区别是什么?实际上,你什么时候需要使用常量而不是变量呢?我知道有人说在程序执行期间信息不会改变时使用常量,但我真的想不出何时不能使用变量代替常量。
变量,如名称所示,会随着时间变化而变化。如果它不变,则不存在“损失”。当您告诉编译器该值不会更改时,编译器可以进行大量优化,例如直接将值内联并且不在栈上分配任何常量的空间。
但是,您不能总是指望编译器足够聪明,能够正确确定一旦设置后一个值是否会更改。在任何编译器无法百分之百确定时,编译器都会以安全为先,并假设其可能会更改。这可能导致各种性能影响,例如避免内联、不优化某些循环、创建不太支持并行处理的目标代码等。
因此,由于可读性也很重要,您应该尽可能使用显式常量,留下变量处理实际可能会更改的事物。
至于为什么使用常量而不是文字数字:
1)它使代码更易读。每个人都知道3.14是什么(希望如此),但并不是每个人都知道3.07是宾夕法尼亚州的所得税率。这是领域特定知识的例子,未来维护您的代码的每个人(例如,税务软件)都可能不知道它。
2)在进行更改时可以节省工作量。如果将来税率更改,去更改每个3.07为3.18将会很烦人。您总是要尽量减少更改,并理想情况下进行单次更改。您必须进行的并发更改越多,就越容易忘记某些事情,导致错误。
3)您可以避免风险错误。想象一下有两个州的所得税率都为3.05,然后其中一个变成了3.18,而另一个仍然是3.07。通过只是进行替换,您可能会遇到严重错误。当然,许多整数或字符串常量值比“3.07”更常见。例如,数字7可以表示一周中的天数和其他内容。在大型程序中,很难确定每个文字值的含义。
4) 对于字符串文本,通常会使用符号名称来允许字符串池在支持多种语言的情况下快速更改。
除了变量和“常量变量”之外,还有一些具有枚举的语言。枚举实际上允许您为一小组常量(例如返回值)定义类型,因此使用它们将提供类型安全性。
例如,如果我有一个星期几和月份的枚举,当我将月份赋值给星期几时,系统会警告我。如果我只使用整数常量,则在将第3天分配给第3个月时将没有警告。您始终希望拥有类型安全性,这将提高可读性。枚举也更适合定义顺序。想象一下,如果您有星期几的常量,现在您想让一周从星期一开始,而不是星期日。
3.14
明显是 ((e*phi)^(phi/2)-3) << 1
。 - Mateen Ulhaq使用常量更多是一种防御性编程的方式,以保护自己免受在凌晨2点或在喝咖啡之前编码时意外更改代码中某个值的影响。
从技术上讲,你也可以使用变量。
startBackgroundProcess();
sleep(1000); // 确保进程已经启动完成
useBackgroundProcesses();
- duckbrain常量相比变量有几个优势。
常量提供了某种程度的保证,即代码无法更改底层值。这对于较小的项目并不重要,但在由多个作者编写的多个组件组成的大型项目中很重要。
常量还为编译器提供了强烈的优化提示。由于编译器知道该值无法更改,因此它不需要从内存中加载该值,并且可以将代码优化为仅适用于常量的确切值(例如,如果const是2的幂,则编译器可以使用移位进行乘除运算)。
常量也是固有的静态的——您可以在头文件中声明常量及其值,并且无需担心定义它的确切位置。
首先是性能优化。
更重要的是,这是为人类读者而设计的。请记住,你的目标受众不仅仅是编译器。在代码中表达自己,避免使用注释,可以帮助你更好地表达。
const int spaceTimeDimensions = 4;
if(gpsSattelitesAvailable >= spaceTimeDimensions)
Good();
对于像C这样的低级语言,常量允许进行多个编译优化。
对于一般的编程语言来说,你并不真正需要它们。高级动态语言,比如Ruby和JavaScript,没有常量(或者至少不是真正的常量)。相反,变量被使用,就像你所建议的那样。
常量是当您只想共享内存且其不会改变时使用的。
const
关键字常用于函数参数,特别是指针,以表明指针所指向的内存不会被函数修改。例如,看看strcpy
的声明:
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
,这些都永远不会发生。此外,const
存储在内存中的其他位置,与普通变量的存储位置相比更加高效。