我无法理解C中符号常量的含义,我确信它们有一个原因,但我似乎无法理解为什么你不会只使用变量.
#include <stdio.h>
main()
{
float fahr, celsius;
float lower, upper, step;
lower = 0;
upper = 300;
step = 20;
printf("%s\t %s\n", "Fahrenheit", "Celsius");
fahr = lower;
while (fahr <= upper) {
celsius = (5.0 / 9.0) * (fahr - 32.0);
printf("%3.0f\t\t %3.2f\n", fahr, celsius);
fahr = fahr + step;
}
}
Run Code Online (Sandbox Code Playgroud)
比.
#include <stdio.h>
#define LOWER 0
#define UPPER 300
#define STEP 20
main()
{
float fahr, celsius;
printf("%s\t %s\n", "Fahrenheit", "Celsius");
fahr = LOWER;
while (fahr <= UPPER) {
celsius = (5.0 / 9.0) * (fahr - 32.0);
printf("%3.0f\t\t %3.2f\n", fahr, celsius);
fahr = fahr + STEP;
}
}
Run Code Online (Sandbox Code Playgroud)
Ted*_*opp 17
(pre)编译器知道符号常量不会改变.它在编译时替换常量的值.如果"常量"在变量中,通常无法确定变量永远不会改变值.因此,编译后的代码必须从分配给变量的内存中读取值,这会使程序稍微变慢.
在C++中,您可以声明一个变量const,它告诉编译器几乎相同的东西.这就是为什么符号常量在C++中不受欢迎的原因.
为什么命名常数是有益的一个很好的例子来自Kernighan和Pike 的优秀书籍编程实践.
§1.5幻数
[...]这个摘录自一个程序,用于在24×80光标寻址终端上打印字母频率的直方图,由于一系列幻数,它们不必要地不透明:
Run Code Online (Sandbox Code Playgroud)... fac = lim / 20; if (fac < 1) fac = 1; for (i = 0, col = 0; i < 27; i++, j++) { col += 3; k = 21 - (let[i] / fac); star = (let[i] == 0) ? ' ' : '*'; for (j = k; j < 22; j++) draw(j, col, star); } draw(23, 2, ' '); for (i = 'A'; i <= 'Z'; i++) printf("%c ", i);该代码包括数字20,21,22,23和27.其中明显相关......或者是它们?事实上,这个程序只有三个关键数字:24,屏幕上的行数; 80,列数; 26,字母表中的字母数.但是这些都没有出现在代码中,这使得数字变得更加神奇.
通过在计算中给主要数字命名,我们可以使代码更容易理解.例如,我们发现数字3来自(80 - 1)/ 26,并且应该有26个条目,而不是27个(一个可以由1个索引的屏幕坐标引起的一个一个错误).进行其他几个简化,结果如下:
Run Code Online (Sandbox Code Playgroud)enum { MINROW = 1, /* top row */ MINCOL = 1, /* left edge */ MAXROW = 24, /* bottom edge (<=) */ MAXCOL = 80, /* right edge (<=) */ LABELROW = 1, /* position of labels */ NLET = 26, /* size of alphabet */ HEIGHT = (MAXROW - 4), /* height of bars */ WIDTH = (MAXCOL - 1)/NLET /* width of bars */ }; ... fac = (lim + HEIGHT - 1) / HEIGHT; if (fac < 1) fac = 1; for (i = 0; i < NLET; i++) { if (let[i] == 0) continue; for (j = HEIGHT - let[i]/fac; j < HEIGHT; j++) draw(j+1 + LABELROW, (i+1)*WIDTH, '*'); } draw(MAXROW-1, MINCOL+1, ' '); for (i = 'A'; i <= 'Z'; i++) printf("%c ", i);现在它更清楚主循环的作用; 它是从0到NLET的惯用循环,表明循环遍及数据元素.此外,调用
draw更容易理解,因为像MAXROW和MINCOL这样的单词提醒我们参数的顺序.最重要的是,现在可以将程序调整为另一种尺寸的显示器或不同的数据.这些数字是神秘的,代码也是如此.
修改后的代码实际上并没有使用MINROW,这很有趣; 人们想知道剩下的1中哪一个应该是MINROW.