我想声明一个常量char数组的常量数组。如果我这样写:
const char foo[] = "Foo";
const char bar[] = "Bar";
const char* const foobar[2] = { foo, bar };
它似乎有效,但如果我尝试使用"the spiral rule"阅读它,则foobar读作:
“foobar是一个常量(??)的数组2到指向char常量的指针”
使用此stack overflow答案,
const适用于它剩下的东西。如果左边没有任何内容,那么它适用于它的权利。
第一个const
将应用于char,第二个const
也适用于相同的char。
两种阅读方式都没有意义,但代码确实有效(至少在Arduino [抱歉])。哪个const
正在制作哪个常数?是否有更合理的方式来编写它?
答案 0 :(得分:8)
正如你所说:
const适用于它剩下的东西。如果左边没有任何内容,那么它适用于它的权利。
const char* const foobar[2] = { foo, bar };
可以重写为:
char const * const foobar[2] = { foo, bar };
现在想象一下封装const
限定符和实体限定的实例:
((char const) (* const)) foobar[2] = // doesn't matter
您已经写过第二个const也适用于同一个字符。这不是真的 - 第二个const
引用*
,这意味着它是一个常量指针。
总而言之, foobar
是一个常量字符常量指针数组。
您可能还想阅读此主题:constant pointer vs pointer on a constant value。
答案 1 :(得分:5)
一个挑剔但重要的观点;在C中,不可能有const
数组。 (参考:C11 6.3.2.3/2)。
看起来像是一个的所有东西实际上都是一个非const数组,其元素是const
。 Link to related discussion。
在您的示例const char* const foobar[2] = { foo, bar };
中,两个const
关键字表示:
文本描述是" foobar是一个指向char常量的常量指针的数组2"。
请注意,指向的字符实际上可能是非常量char
,但又有一个小而重要的区别,因为const char *
可以指向const和非const。第一个const
的效果是说我们可能不知道字符是否为常量,因此我们无法安全地写入它们,因此如果我们尝试将编译器生成错误使用此指针或写入它们。
答案 2 :(得分:3)
foobar
是指向const
的{{1}}指针数组。数组总是不变的,没有办法明确地使它成为const char
。
在函数参数的声明中,数组衰减为指针,并且const
指针确实存在;在这种情况下,const
可以放在const
内。这些是等价的:
[]
螺旋规则并不完美(某些复杂的声明失败),我个人觉得它与限定符(void func(int foo[const]) { ... }
void func(int *const foo) { ... }
,const
等)结合起来并没有用。我不知道有什么准确地呈现规则而是语法本身(C11 6.7和6.7.6)。
然而,在这种情况下,似乎有效:
volatile
“ +--------------+
| +---+ |
| ^ | |
const char *const foobar[2] |
^ ^ | |
| +----------+ |
+---------------------+
是指向foobar
的{{1}}指针的数组(包含2个元素)。”