有一个判断 C 语言的声明式的技巧,那就是“从右往左读”,C++ 创始人 Bjarne Stroustrup 在其著作《The C++ Programming Language》中推荐了这种方法,《C 专家编程》中也提及了这种技巧。相比于其他的“根据 const 与其他词素的距离判断”、“根据 const 的前后关系判断”等等,个人认为这是最人性化的方法。从某种意义上来说,C
编译器在进行词法分析的时候巧合地运用了这种范式来进行语义转换,这一点在 Backus(上下文无关法) 范式中也有体现。
具体的方法是:
const char * A:A 是一个指针,指向 const char。
char const * A:A 是一个指针,指向 const char。
char * const A:A 是一个 const 指针,指向 char。
const char * const A:A 是一个 const 指针,指向 const char。
const char const * const A:A 是一个 const 指针,指向 const char,后面两个(从右往左读)有一个是多余的。
看到给出的示例:
const char* date;
这是一个指向 const char 的指针,这说明指针本身可变,但是其指向的 char 是不可变的,而 date = "new string" 中常量
字符串其实是一个指针,因为指针可变,所以这里没问题。
但是如果写成 char* const date,那么这就是一个不可变的指针,但是其指向的 char 是可变的,这时候写 date = "new string" 就会报错:
error: cannot assign to variable 'date' with const-qualified type 'char *const'
但是如果尝试如下语句:
char* const date = "Hello, world!";
date[0] = 'H';
编译能通过,但是运行时会出错:
zsh: bus error
总线错误是怎么引起的呢?不是指向的 char 可变吗?对,指向的 char 可变,所以编译能通过,但是赋给 date 的是一个字面字符串,按照 C 语言操作内存的机制,尝试更改字面字符串的会引起 bus error,至于具体的原因,可以继续深入了解 C 语言的编译机制和运行原理,这里不再赘述。
追问谢谢,讲的很清楚(虽然我怀疑你是从哪里复制黏贴的),按我的理解const *char是 指针指向一个不可修改的变量(如果指针指向的变量前没有const,那么能修改吗)。char* const是指针在赋初值后就不能修改了是吗(如果是常量也不能修改吗)。
追答“const *char是 指针指向一个不可修改的变量”这里是 const char *(应该是打错了吧...),其他的都对,另外是真的推荐这种“从右往左读”的判断声明式意思的方法,因为编译器生成语法树的时候就是这么做的,这种方法不仅对于判断 const 有用,无论那个声明式多么复杂,都可以用这种方法解决,比如说:
const char * Func_A (int const * Func_B (void * a, int b), int c);
这是一个函数声明,“从右往左”读:
首先是 Func_A,返回一个参数,这个参数 is a pointer to const char,即一个指向 const char 的指针;接受两个参数,第一个参数是一个函数,这个参数 Func_B 接受一个 void * 和一个 int,返回一个参数,这个参数 is a const pointer to int,即一个 const 指针,指向一个 int;Func_A 的第二个参数是一个 int。
下面是《Expert C Programming》中的一个例子(手头没有中文电子版,位置大概是靠前面的几章吧?):
![](https://video.ask-data.xyz/img.php?b=https://iknow-pic.cdn.bcebos.com/023b5bb5c9ea15cebe651576a6003af33b87b2c2?x-bce-process=image%2Fresize%2Cm_lfit%2Cw_600%2Ch_800%2Climit_1%2Fquality%2Cq_85%2Fformat%2Cf_auto)