多个const限定符的含义是什么?

19

代码:

const char* const* const* foo(int bar);

我之前见过双重const的用法,可以防止指针被修改。这是我第一次看到三重const,不知道它的用途是什么。


你可以为基本类型设置一个const,并且每个*再加上一个const。因此,const char *const *const *const foo(int bar);是有效的。 - pmg
每个 * 都会增加一层间接性。而且每一层间接性也可以被 cv 限定。 - StoryTeller - Unslander Monica
2
这意味着每个指针间接级别都是const。 - thumbmunkeys
3
为什么有人需要常量指针的常量指针? - Lukáš Rutar
4
同样的原因,你可能需要使用任何const内容。 - Oliver Charlesworth
1
使用cdecl翻译器 - ItsMe
4个回答

19

在您的示例中,除了最高级别的间接引用外,所有都被标记为const

const char            /* const qualified base level */
    *const            /* const qualified level 1 */
    *const            /* const qualified level 2 */
    *                 /* regular level 3 */
    foo(int bar);

foo 是一个接受 int 类型参数并返回一个常规指针的函数。
它返回的指针指向一个 const 修饰的指针,
该指针又指向另一个 const 修饰的指针
该指针指向一个 const 修饰的 char 类型。


最喜欢这个答案了 :) 谢谢! - Learath2
当您完全取消引用由该类型指针指向的数据时,我想看到您的内存层次结构的表情... :) - Manu343726

14

如果你有一个多级指针,你会有几个指针变量。例如:

char*** foo;

使用如下方式访问:

| foo | pointer1 | pointer2 | string |
   |    ^     |    ^     |    ^
    \___/      \___/      \___/

您可以将内存中的这四个位置都标记为const,就像声明中的方式一样。

const char *const *const *const foo;

然而,最好避免成为一个三星程序员。


我见过 char *** 的主要(合理)用途是建模“out”参数,告诉调用者有关字符串数组的信息。在其中添加所有这些 const 只会让一切更加混乱... - Donal Fellows
@DonalFellows作为编写此代码的“三星程序员”,你是对的,它旨在传递一个字符串数组。但你错了,它只会增加混乱。它可以防止用户代码干扰该数组或其中一个字符串。 - fstd
@fstd 我知道如何使用多个const,但它仍然会让人感到不安。 - Donal Fellows
@DonalFellows,我不是在向您解释它的工作原理,而是为其使用辩护。不明白它有什么可怕之处--相反,省略const将导致可怕的情况。这是库代码。 - fstd

8

哈哈,关于const的概念常常让人困惑。

基本上,如果它限定了一个指针,那么它就会立即应用于其左侧的指针。例如:

char *const c;

使得c成为指向char的只读指针。
const char *c;

使 c 成为指向只读的 char 指针,尽管您可以更改 c 指向的位置。
当然,指针和其指向的内容都可以被设置为只读:
const char *const c;

这将使c成为指向只读char的只读指针。通过前面的声明,你可以修改*c,但是你不能修改c(即你不能使它指向其他地方)。通过第二个声明,你可以赋值给c,但不能赋值给*c,第三个声明则既不能修改指针所指向的位置,也不能修改指向的对象。
这个规则适用于多级间接引用。对于你的情况,你可能想要将const关键字与它们所修饰的相应指针重新分组。这主要是一个空格问题,但是它应该像这样:
const char *const *const *foo(int bar);

这会使得foo返回一个指向只读指针的只读指针,该指针又指向一个只读的char。仔细阅读:注意在给定以下代码时:

const char *const *const *ptr = foo(0);

那么您知道将值分配给ptr是合法的,但任何其他赋值都是非法的,也就是说,您不能将值分配给*ptr**ptr***ptr

1
我不明白 ptr = "xpto" 怎么合法,因为 "xpto" 不是一个 const char* const* const - Lightness Races in Orbit
@LightnessRacesinOrbit 哎呀,完全同意。我已经删除了那部分,感谢你的反馈。 - Filipe Gonçalves
const char * 中已经没有 const 的痕迹了。 - Jan Hudec
@JanHudec 那里的 const 并没有限定指针,所以该参数不适用(它仅在 const 限定指针时才适用)。但如果您愿意,也可以将其写为 char const * - user253751

4

foo返回一个指向常量字符的常量指针,该指针指向另一个指向常量指针的指针。请参阅spiral rule

int bar;
const char* const* const* ptr = foo(bar);

基本上你无法改变*ptr**ptr***ptr的任何一个。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接