区分指针常量和常量指针的技巧

如何判断常量指针(constant pointer)和指针常量(pointer to a constant)是件很头疼的事,如果是一级指针还好,可以强行记住三种形式,如果是多级指针,那就等着受虐吧。我们先看看教科书的技巧

1. 教科书的方法

Bjarne在他的The C++ Programming Language里面给出过一个助记的方法: 
把一个声明从右向左读。

char * const cp; ( * 读成 pointer to ) 
cp is a const pointer to char

const 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函数的形参类型是const char **pp; 利用上面所说的规律,只有**pp = ‘w’;这样访问是不行的。其它都可以,因此答案是ACD。

实际上,即使foo函数声明成这样,A也是错的:foo(char **pp);

原因是,p指向的字符串”hello”是存在放常量区的,不能改变。所以我们用字符串字面值给字符指针赋值的时候,一般都将字符指针定义成指针常量:

const char *p = "hello";
*p = 'w';                   /*编译错误!*/
char *q = "hello";
*q = 'w';                   /*编译正确,运行时错误!*/

3. 总结

最近再整CSDN排名,如果本篇博客对你有用就评论一下帮我刷个积分吧。

你可能感兴趣的:(CTA)