const char **,char *const *,char ** const

一、出人意料的Warning

test_cpp.c编程

#include <stdlib.h>
#include <stdio.h>

int main()
{
        char c = 'c';

        char *p = &c;

        char **pp = &p;
        const char **cpp = &p;
        char const **c_pp = &p;
        char  * const *p_const_p = &p;
        char  ** const ppc = &p;

        return 0;
}

编译的时候有以下warning:ubuntu

x@ubuntu:~/Desktop/const$ gcc text_cpp.c
text_cpp.c: In function ‘main’:
text_cpp.c:11:21: warning: initialization of ‘const char **’ from incompatible pointer type ‘char **’ [-Wincompatible-pointer-types]
  const char **cpp = &p;
                     ^
text_cpp.c:12:22: warning: initialization of ‘const char **’ from incompatible pointer type ‘char **’ [-Wincompatible-pointer-types]
  char const **c_pp = &p;
                      ^

看到上面的warning,第一时间就是有点懵,和"经验不符“,咱们常见的是以下用法:ide

#include <stdlib.h>
#include <stdio.h>

int main()
{
         char c = 'c';

        const char *p = &c;
        char const *q = &c;
        char *const r = &c;

        return 0;
}

上述用法都是ok的,编译不会有warning。指针

二、 解释

2.1 理论背景介绍

查了不少资料,大体搞清楚了上面warning的缘由。上面warning缘由在《C专家编程》中有解释,并且也参考了本文后面网址的资料。code

先来看看ANSI C中的规定:“两个操做数都是指向有限定符或无限定符的相容类型的指针,左边指针指向的类型必须具备右边指针指向类型的所有限定符“。这句话的前半句强调类型,后半句强调限定符(修饰符)。 出现编译warning的地方,若是不看修饰符const,赋值彻底没有问题,问题出如今const修饰符。仍是上面那句话,须要进行两点说明:
(1) 相容类型:在《ANSI C》的6.2.7节中,对相容类型(compatible type)的定义为:Two types have compatible type if their types are the same.
(2) 指针指向类型:字面意思理解,应该指的是对指针仅进行一次解引用获得的类型。对象

2.2. 应用理论解释

根据上面的说明,分别对下图中的三种状况进行解释:it

状况一:

char **pp = &p等式两边的两个操做数都没有限定符去,且pp指向的是char *类型,&p指向也是char *类型,是相容类型,符合前面那句话的前半句,两个操做数都是指向无限定符的相容类型指针,那么这个赋值ok,没有任何问题。
const char **,char *const *,char ** constio

状况二

char * const *pp = &p。pp 指向的是char * 类型,&p指向是char *类型,等式两边的类型相容,可是等式左边pp指向的类型有const关键字修饰,右边操做数没有限定符。指向类型一个有限定符,一个没有限定符,不符合前面那句话的前半句:两个操做数都是指向有限定符或无限定符的相容类型的指针编译

须要注意的是左边的const是pp指向类型*pp的限定符,指的是不能经过对pp一次解引用改变p的值,也就是说const是左边操做数指向类型的限定符。function

接着看是否符合后半句,左边指针指向的类型有const限定符,右边指针指向的类型没有限定符,符合后半句:左边指针指向的类型必须具备右边指针指向类型的所有限定符。 能够这么理解左边指针指向的限定符集合是A={const, Ø}, 右边指针指向类型的限定符集合是B={Ø},很显然 A 具备B的全部限定符。
const char **,char *const *,char ** const

状况三

const char **pp = &p等式左边pp指向的类型是const char *,&p指向是char *类型,不是相容类型。这是由于pp指向的类型是 *pp(const char *), *pp (const char *)没有限定符,const 限定符修饰的不是*pp, 而是*pp指向的类型**p(char), 显然这是对pp解引用二次了;&p指向的类型是p(char *)。 核心问题要肯定const限定符修饰的对象。
const char **,char *const *,char ** const

相关文章
相关标签/搜索