如何判断常量指针(constant pointer)和指针常量(pointer to a constant)是件很头疼的事,如果是一级指针还好,可以强行记住三种形式,如果是多级指针,那就等着受虐吧。我们先看看教科书的技巧
1. 教科书的方法
Bjarne在他的The C++ Programming Language里面给出过一个助记的方法:
把一个声明从右向左读。char * const cp;
( * 读成 pointer to )
cp is a const pointer to charconst char * p;
p is a pointer to const char;
2. 技巧 当定义二级三级甚至多级指针常量/常量指针,用上面的方法就会很复杂。
定义指针常量/常量指针无非是*和const修饰符的位置进行排列,我自己观察到一个规律:
const修饰符和变量名之间有几个*,那么在用这么多*解引用时,就不能改变这个值。
- 例如,
char * const p1 = &ch1; /* (1)第一种形式 */ const和变量名p1之间有0个*,那么p1 = &ch2; 这样就是错的。
- 再如,
char const *p2 = &ch2; /*(2)第二种形式*/ const char *p2 = &ch2; /*(3)第三种形式*/ const和变量名p2之间有一个*,那么*p='b'; 这样就是错的,
- 再举一个复杂一点的例子,
char ch1 = 'a'; char ch2 = 'b'; char *p1 = &ch1; char *p2 = &ch2; const char **pp = &p1; 因为const到变量名pp之间有2个*,那么**pp = 'b'; 这样就是错的。而, *pp = &ch2; 或 pp = &p2; 这样都是对的。
- 更高级的例子,
char ch1 = 'a'; char ch2 = 'b'; char *p1 = &ch1; char *p2 = &ch2; char * const*pp = &p1; 因为const到变量名pp之间有1个*,那么*pp = &ch2; 这样就是错的。而, **pp = ch2; 或 pp = &p2; 这样都是对的。
- 掌握了这个规律,再看谷歌的这道面试题是不是很简单呢。
[题目]
const char *p="hello";
foo(&p); //函数foo(const char **pp)
下面说法正确的是[]
A.函数foo()不能改变p指向的字符串内容
B.函数foo()不能使指针p指向malloc生成的地址
C.函数foo()可以使p指向新的字符串常量
D.函数foo()可以把p赋值为 NULL.
解答:实际上,即使foo函数声明成这样,A也是错的:foo(char **pp);
foo函数的形参类型是const char **pp; 利用上面所说的规律,只有**pp = ‘w’; 这样访问是不行的。其它都可以,因此答案是ACD。
原因是,p指向的字符串”hello”是存在放常量区的,不能改变。所以我们用字符串字面值给字符指针赋值的时候,一般都将字符指针定义成指针常量:
const char *p = "hello";
*p = 'w';
/*编译错误!*/
char *q = "hello";
*q = 'w';
/*编译正确,运行时错误!*/
3. 总结 【区分指针常量和常量指针的技巧】最近再整CSDN排名,如果本篇博客对你有用就评论一下帮我刷个积分吧。