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

1、出人意料的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:

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,第一时间就是有点懵,和"经验不符“,我们常见的是如下用法:

#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、 解释

2.1 理论背景介绍

查了很多资料,大致搞清楚了上面warning的原因。上面warning原因在《C专家编程》中有解释,而且也参考了本文后面网址的资料。

先来看看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. 应用理论解释

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

情况一:

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

情况二

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

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

接着看是否符合后半句,左边指针指向的类型有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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值