首先来看一段代码:
#include<stdio.h>
void foo(const char **p) { }
void main(int argc, char **argv)
{
foo(argv);
return ;
}
我们对这段代码进行编译,发现它报出了警告:
test.c: In function ‘main’:
test.c:14:9: warning: passing argument 1 of ‘foo’ from incompatible pointer type [-Wincompatible-pointer-types]
foo(argv);
^
test.c:10:6: note: expected ‘const char **’ but argument is of type ‘char **’
void foo(const char **p) { }
^
一般来说,对程序运行结果没有影响的警告我们会进行忽略,但是这个程序很短,非常易读,所以我们并不认为程序中有引发警告的bug,但是它却爆出了警告,这就耐人寻味了。
要想了解这个问题,我们需要阅读ANSI C标准。
如果你对上面的代码所论述的问题还没有那么清楚,请思考如下代码的运行结果:
#include<stdio.h>
void main(int argc, char **argv)
{
char *cp;
const char *ccp;
ccp = cp;
cp = ccp;
}
你觉得两个赋值语句有什么不同?emmmm,事实是cp = ccp
会爆出警告。
我们来阅读一下ANSI C的标准吧~
要使上述的赋值形式合法,必须满足下列条件之一:
- 两个操作数都是指向有限定符或无限定符的相容类型的指针。
- 左边指针所指向的类型必须具有右边指针所指向类型的全部限定符。
好了,我们可以对先对第二个代码进行分析了:
cp是一个指向char类型的指针,无限定符;ccp是一个指向char类型的指针,有限定符。所以当ccp为左操作数的时候,它含有右边指针(无)所指向类型的全部限定符。因此没有警告,反之cp = ccp
有警告。
那么我们来分析一下第一个代码:
argv是一个指向char*类型的指针,p是指向一个const char*的指针,foo(argv)
相当于是执行了p = argv
的赋值操作,而它们根本就是不相容的类型,所以也会产生一条诊断信息。
所以对于这种细微的东西,了解之后会发现原来是很有趣的一件事情。