如何看复杂的变量声明?带限定符和指针

例如:

const char **p;
char *const *p;
char **const p;

阅读 C 语言中的复杂变量声明时,可以先找到变量名,再按“先近后远、先右后左”的顺序看它周围的符号;如果遇到括号,则括号里的部分优先。对于指针和 const,关键是判断 const 修饰的是谁:它在 左边时通常修饰被指向的数据;它在 右边时修饰这个指针本身。

先看:

const char **p;

p 是一个指针;它指向的内容仍然是一个指针;第二层指针最终指向的是 const char。也就是说,p 是“指向指针的指针”,而最里面的字符内容不能通过这个类型被修改。可以读作:p 是一个指针,指向另一个指针,后者指向常量字符。

再看:

char *const *p;

从变量名 p 开始看,p 先和左边最近的 结合,所以 p 是一个指针。这个指针指向的内容是 char const,也就是一个“常量指针”。这个常量指针本身不能被改成指向别处,但它指向的 char 内容不是 const,可以通过它修改。

因此,char const p 可以读作:p 是一个指针,指向一个常量指针,这个常量指针指向 char

最后看:

char **const p;

这里 const 在最外层的 右边,所以它修饰的是变量 p 这个指针本身。也就是说,p 是一个常量指针,不能再指向别的地址;它指向的内容是 char ,而这个 char * 又指向 char

可以读作:p 是一个常量指针,指向一个 char * 指针,后者指向 char

总结如下:

const char **p;   // p 是指向指针的指针,最里面的数据是 const char
char *const *p;   // p 是指向 const 指针的指针,那个 const 指针指向 char
char **const p;   // p 本身是 const 指针,指向 char *

一个实用判断方法是:从变量名开始向外读,每看到一个 就加一层“指针”;每看到一个 const,就看它贴近哪一层。如果 const 贴近的是类型名,比如 const char,它修饰数据;如果 const 贴近的是某个 的右边,比如 *const,它修饰那一层指针。

Leave a Reply