C中有const吗?

这个问题可能是天真的,但是:

  • C中有const关键字吗?
  • 从哪个版本?
  • C和C ++中的const之间是否存在任何语义和/或语法差异?

C和C ++在const关键字方面没有语法上的区别,除了一个比较模糊的地方:在C中(因为C99)你可以声明函数参数为

 void foo(int a[const]); 

相当于

 void foo(int *const a); 

宣言。 C ++不支持这种语法。

存在语义差异。 正如@Ben Voigt已经指出的那样,在C const声明中不会产生常量expression式,即在C语言中,不能在case标签中使用const int对象,在非VLA数组中使用位域宽度或数组大小声明(所有这一切都可能在C ++中)。 另外, const对象在C(C ++中的内部链接)中默认有外部链接。

至less有一个语义上的差异,本没有提到。 C ++语言的正确性规则支持以下标准转换

 int **pp = 0; const int *const *cpp = pp; // OK in C++ int ***ppp = 0; int *const *const *cppp = ppp; // OK in C++ 

这些初始化在C中是非法的

 int **pp = 0; const int *const *cpp = pp; /* ERROR in C */ int ***ppp = 0; int *const *const *cppp = ppp; /* ERROR in C */ 

一般来说,在处理多级指针时,C ++说你可以在任何深度的间接性中添加const限定,只要你还可以在顶层添加const限定。

在C中,只能将const限定添加到顶层指针指向的types,但不能更深入。

 int **pp = 0; int *const *cpp = pp; /* OK in C */ int ***ppp = 0; int **const *cppp = ppp; /* OK in C */ 

同样的基本一般原则的另一个performanceforms是常量正确性规则在C和C ++中使用数组。 在C ++中,你可以做

 int a[10]; const int (*p)[10] = &a; // OK in C++ 

尝试在C中执行相同的操作将导致错误

 int a[10]; const int (*p)[10] = &a; /* ERROR in C */ 

前两个问题在这里回答: C中的Const

是的,在C和C ++中const之间的语义有很多不同。

  • 在C ++中,适当types的constvariables是整型常量expression式 ,可用于上下文中,如数组边界和枚举定义。 在C中,他们不是,也不是。

  • 在C ++中, const全局variables自动具有static链接,所以你可以把它们放在头文件中。 在C中,这些variables具有外部链接,并且在链接时会产生重复的定义错误。

是的,有一个const关键字。 这是1989年标准的一部分。

至于兼容性,这里是Harbison&Steele第5版的一段:

具有types限定符const但没有显式存储类的顶级声明在C ++中被认为是static ,但在C中是extern 。为了保持兼容性,检查顶层的const声明并提供一个显式的存储类。 在C ++中,string常量是隐含的const ; 他们不在C

另外两个区别:

是的,自从ANSI C(又名C89)以来, const一直存在。

它肯定出现在我的“The C Programming Language(2nd Edition)”,Kernighan&Ritchie (1988年出版)中。

相关摘录:

constvolatile属性在ANSI标准中是新的。 const的目的是宣布可能被放置在只读存储器中的对象,并且可能增加优化的机会。

C中的语义与C ++中的不同,例如

 unsigned const a = 10; unsigned A[a]; 

在文件范围内在C ++中有效,但不在C中

是。 const从C89出现在C中。

这里是一个很好的阅读是关于在C中的const关键字的行为 。

是的,C中有一个const关键字。从C90开始就一直存在。

在语法上,它可以发生在与C ++相同的地方。 从语义上讲,这是一个更为宽松,IIRC。

根据ESR ,在ANSI C草案提案标准中增加了const 。 Eric Giguere在1987年对ANSI C的总结证实了这一点。

编辑: 这看起来像草案本身 – search“3.5.3types限定符”。

在C中有一个“const”关键字,并且是一个很长的时间。 如果一个variables被指定为“const”,则写入该variables是被禁止的。 此外,在某些环境中,声明为“const”的variables可能位于与其他variables不同的数据段中。 该数据段可以提供硬件写保护,对于embedded式系统,可以存储在ROM或闪存中而不是存储在RAM中(在一些具有比RAM更多的ROM或闪存的处理器上的重要区别 – 例如128K闪存3.5K RAM或2K ROM和96字节RAM)。

请注意,编译器通常不会对“const”值或涉及它们的expression式进行任何推理。 如果我说“const char foo [] =”你好“;” 然后稍后引用foo [1],编译器将加载foo []存储在其中的任何值(最可能是'e')并使用加载的值。 有时候这样做有用地允许在编译的代码图像中修补值,但是有时它只是浪费了代码。

如果你想定义一个编号为编译时“可replace”常量,最好的方法,至less对于整数常量,可能是使用“枚举”。 例如,“enum {woozle = 19;}”将导致19代替整个代码中的“woozle”。 请注意,不像文本replace; 枚举声明遵守适当的范围规则。