const char**a;
char *b[] = {0};
a = b;
对于上面这段代码,GCC编译器会在"a=b"一句上报告警告,提示不匹配的指针类型。
感觉非常奇怪,非const向const赋值,居然都报错?在网络上搜索相关问题,得到的信息大致如下:
在ANSI C标准中有这么一句话:
什么是合法的赋值形式呢?两个操作数都是指向有限定符或者无限定符的相容的指针,左边指针所指向的类型必须具有右边指针指向类型的全部限定符。
于是,对于语句:
char *test1;
const char *test2;
test2 = test1;
我们来看,左操作数是一个指向有const限定符的char指针,右操作数指向没有限定符的char指针,而char和char本身是相容的,左操作数指向的类型也具有右操作数指向类型的限定符(这里是空),因此,可以赋值。
对于前面的语句"a=b",两者都是指向指针的指针,后者指向的是char *,前者指向的是const char*。 const char*并不是一个有限定符的类型,它是"指向有const限定的char类型的指针"。
所以, const char **和 char **都是没有限定符的指针,但他们指向的类型不一样,前者指向 const char *,后者指向 char *。因此他们并不相容。
看了上面这些东西,实在太绕,抛出一堆概念和规则,并且没有“为什么”。用规则本身来解释问题,而很少谈论为什么要有这样的规则。
那么,这什么要有这样的规则呢?
举个例子,看看如果前面的语句"a=b"没有问题的话,会有什么问题。
const char* s = "abc"; /* s指向常量字符串 */
char* p0 = 0;
char** p1 = &p0; /* p1指向p0 */
const char** p2 = p1; /* p2也指向p0(char**赋值给const char**,先假设这样是成立的) */
*p2 = s; /* p2指向的p0与s具有相同指向,非const指针p0指向了常量字符串 */
*p0 = 'A'; /* 通过p0修改常量字符串,结果一般情况下是程序崩溃 */
这就是规定产生的原因……