正如在最近几个问题中所讨论的那样,const在C中声明限定变量(与constC++中的变量相反,或者const在C中指向变量)通常用于非常少的目的.最重要的是,它们不能用于常量表达式.
话虽如此,constC 中合格变量的合法用途是什么?我可以想到最近在我使用的代码中出现的一些,但肯定必须有其他代码.这是我的清单:
使用它们的地址作为指针的特殊sentinel值,以便永远不会比较任何其他指针.例如:char *sentinel(void) { static const char s; return &s; }或者仅仅const char sentinel[1];因为我们只关心地址,如果对象被写入它实际上并不重要,唯一的好处const是编译器通常将它存储在由mmap可执行文件支持的只读存储器中或零页面的副本.
使用const限定变量从库(尤其是共享库)导出值时,值可能会随库的新版本而更改.在这种情况下,简单地#define在库的接口头中使用将不是一个好方法,因为它会使应用程序依赖于它构建的库的特定版本中的常量值.
密切相关的以前的使用,有时要公开从库中预先定义的对象到应用程序(典型的例子是stdin,stdout和stderr从标准库).使用该示例,extern FILE __stdin; #define stdin (&__stdin)由于大多数系统实现共享库的方式,这将是一个非常糟糕的实现 - 通常它们需要将整个对象(此处FILE)复制到链接应用程序时确定的地址,并引入对大小的依赖性对象(如果重建库并且对象的大小发生变化,程序将中断).使用const指针(不是指针const)在这里修复所有问题:extern FILE *const stdin;,在哪里const指针被初始化为指向static库内部某处的预定义对象(它本身可能已声明).
数学函数,字符属性等的查找表.这是我最初忘记包含的一个显而易见的表,可能是因为我在考虑const算术/指针类型的各个变量,因为这是问题主题首次出现的地方.感谢Aidan引发我的记忆.
作为查找表的变体,实现状态机.艾丹提供了一个详细的例子作为答案.我发现相同的概念在没有任何函数指针的情况下通常也非常有用,如果你可以根据几个数字参数对每个状态的行为/转换进行编码.
其他人对constC中的限定变量有一些巧妙的实际用途吗?
const在嵌入式编程中经常用于映射到微控制器的GPIO引脚.例如:
typedef unsigned char const volatile * const tInPort; typedef unsigned char * const tOutPort; tInPort my_input = (tInPort)0x00FA; tOutPort my_output = (tOutPort)0x00FC;
这两个都阻止程序员意外地改变指针本身,这在某些情况下可能是灾难性的.该tInPort声明还防止从程序员改变输入值.
使用volatile可防止编译器假定my_input缓存中将存在最新值.因此,任何读取my_input都将直接进入总线,因此始终从器件的IO引脚读取.