容易混淆的const

来源:互联网 发布:资源共享室软件 编辑:程序博客网 时间:2024/04/29 16:24
首先,我们来看下面一段代码,
#include <stdio.h>

void foo(const char **p)
{
printf("do nothing, only test how to use const.\n");
}

void main(int argc, char **argv)
{
foo(argv);
printf("compiled successfully !\n");
}
在VC6.0中编译这段代码,编译器给出如下错误:
error C2664: 'foo' : cannot convert parameter 1 from 'char ** ' to 'const char ** '
        Conversion loses qualifiers

在ANSI C标准第6.3.2.2节中讲述约束条件的小节中有这么一句话:
每个实参都应该具有自己的类型,这样它的值就可以赋值给与它所对应的形参类型的对象(该对象的类型不能含有限定符)。
这就是说参数传递过程类似于赋值。
第6.3.16.1节中关于简单赋值部分的约束条件:
要使上述的赋值形式合法,必须满足下列条件之一:
两个操作数都是指向有限定符或无限定符的相容类型的指针,左边指针所指向的类型必须具有右边指针所指向类型的全部限定符。
在下面的代码中:
char * cp;
const char *ccp;
ccp = cp;
1.左操作数是一个指向有const限定符的char的指针。
2.右操作数是一个指向没有限定符的char的指针。
3.char类型与char类型是相容的,左操作数所指向的类型具有右操作数所指向类型的限定符(无),再加上自身的限定符(const)。
但是,反过来就不能赋值了。
cp = ccp; //结果产生编译错误
标准6.1.2.5节中讲述实例的部分声称:
const float *类型并不是一个有限定符的类型--它的类型是“指向一个具有const限定符的float类型的指针”,也就是说const限定符是修饰指针所指向的类型,而不是指针本身。
由于char **和const char **都是没有限定符的指针类型,但它们所指向的类型不一样(前者指向char *,后者指向const char *),因此它们是不相容的。因此类型为char **的实参与类型为const char **的形参是不相容的,违反了标准第6.3.2.2节所归定的约束条件。

#include <stdio.h>

void foo(const char *p)
{
printf("do nothing, only test how to use const.\n");
}

void main(int argc, char **argv)
{
char *cp;
foo(cp);
printf("compiled successfully !\n");
}

在这种情况下,代码是可以编译通过运行的。
const最有用之处就是用它类限定函数的形参,这样函数将不会修改实参指针所指的数据,但其他的函数却可能会修改它(如上)。

小启发:
const并不能把变量变成常量,在一个符号前面加上const限定符只是表示这个符号不能被赋值,也就是它的值对于这个符号来说是只读的,但它并不能防止通过程序的内部(甚至是外部)的方法修改这个值。
const int limit = 10;
const int * limitp = &limit;
int i = 27;
limitp = &i;
这段代码表示limitp是一个指向常量整型的指针,这个指针不能用于修改这个整型数,但在任何时候,这个指针本身的值却可以改变。
const和*的组合通常只用于在数组形式的参数中模拟传值调用。

reference:《Expert C Programming》

原创粉丝点击