我想声明一个常量char数组的常量数组.如果我这样写:
const char foo[] = "Foo";
const char bar[] = "Bar";
const char* const foobar[2] = { foo, bar };
Run Code Online (Sandbox Code Playgroud)
它似乎工作,但如果我尝试使用"螺旋规则"读取它,foobar读作:
"foobar是一个常量(??)的数组2到指向char常量的指针"
使用这个堆栈溢出答案,
const适用于它剩下的东西.如果左边没有任何内容,则它适用于它的权利.
第一个const将应用于char,第二个const也适用于相同的char.
两种阅读方式都没有意义,但代码确实有效(至少在Arduino [抱歉]).哪个const是常数?是否有更合理的方式来编写它?
如你所说:
const适用于它剩下的东西.如果左边没有任何内容,则它适用于它的权利.
const char* const foobar[2] = { foo, bar };
Run Code Online (Sandbox Code Playgroud)
可以重写为:
char const * const foobar[2] = { foo, bar };
Run Code Online (Sandbox Code Playgroud)
现在假设包含const限定符和实体限定的paratheses :
((char const) (* const)) foobar[2] = // doesn't matter
Run Code Online (Sandbox Code Playgroud)
你已经写过第二个const也适用于同一个char.这不是真的 - 第二个const指的是*,这意味着它是一个常量指针.
总而言之,foobar是一个常量字符常量指针数组.
您可能还想要读取此线程:常量指针与常量值上的指针.
foobarconst是一个指向 的指针数组const char。数组始终是常量,没有办法显式地使其成为常量const。
在函数参数的声明中,数组衰减为指针,并且const指针确实存在;在这种情况下,const可以将其放入[]. 这些是等效的:
void func(int foo[const]) { ... }
void func(int *const foo) { ... }
Run Code Online (Sandbox Code Playgroud)
螺旋规则并不完美(对于某些复杂的声明它会失败),而且我个人认为它与限定符( 等)结合起来没有const帮助volatile。除了语法本身(C11 6.7 和 6.7.6)之外,我不知道有什么可以准确地呈现规则。
然而,在这种情况下,它似乎有效:
+--------------+
| +---+ |
| ^ | |
const char *const foobar[2] |
^ ^ | |
| +----------+ |
+---------------------+
Run Code Online (Sandbox Code Playgroud)
“是一个指向 的指针foobar的数组(有 2 个元素)。”constconst char
一个挑剔而重要的观点; 在C中,不可能有一个const数组.(参考:C11 6.3.2.3/2).
看起来像是一个的所有东西实际上都是一个非const数组,其元素是const. 链接到相关讨论.
在您的示例中const char* const foobar[2] = { foo, bar };,这两个const关键字表示:
文本描述是"foobar是一个指向char常量的常量指针的数组2".
注意那个小但重要的区别是指向的字符实际上可能是非常量的char,因为a const char *可以指向const和非const.第一个的效果const是我们可能不知道字符是否是const,因此我们无法安全地写入它们,因此如果我们尝试使用此指针写入它们,编译器将生成错误.