亲宝软件园·资讯

展开

C语言const

lonely-hermit 人气:0

一、int const a / const int a

int 和const 都作为一个类型限定词,有相同的地位,所以谁在前谁在后无所谓了,标题中的这两种写法是一致的。

这是我们常规的用途,我们发现这样的话我们对a已经不能做任何修改了。

int main() {
    int const a = 10;
    printf("%d\n",a);
    return 0;
}

真的不能修改吗?未必的

int main() {
    int const a = 10;
    int *p = &a;
    *p = 20;
    printf("%d\n",a);
    return 0;
}

成功修改,这是为什么呢,其实也很简单,这与编译器有关,gcc编译器中const是通过编译器在编译的时候执行检查来确保实现的,也就是检查的时候我发现你没有修改a的值,那我就认为你是对的。更深入一层的原因,是因为gcc把const类型的常量也放在了data段,其实和普通的全局变量放在data段是一样实现的,只是通过编译器认定这个变量是const的,运行时并没有标记const标志,所以只要骗过编译器就可以修改了。

这个本质上是C语言的问题,因为C语言就没有强制要求说const就是不能修改的,所以在C语言中使用const,就好象是 一种道德约束而非法律约束,所以大家使用const时更多是传递一种信息,就是告诉编译器、也告诉读程序的人,这个变量是不应该也不必被修改的。而且我的理解中,这个东西其实设置为了强制不可变在某种程度上不也就限制了C语言的灵活性嘛,c的奇淫巧技不就依靠C语言的灵活性实现的嘛,所谓bug变特性,我的猜测哈,不知道丹尼斯·里奇是不是也是这么想的。

二、const int(*p)/int const(*p)

其实标题是很好理解的,我们修饰了*p,使得p的指向不能被改变了。

int main() {
    int a = 10;
    int const (*p) = &a;
    printf("%d\n",*p);
    return 0;
}

上面的程序很好理解,p指向了a,p被const修饰,指向的对象a已经不能被修改了,下面的程序输出20就说明出了问题,这个还是上面我们讲到的那个问题,这是一个君子约定。

int main() {
    int a = 10;
    int const (*p) = &a;
    a = 20;
    printf("%d\n",*p);
    return 0;
}

下面的四种写法等价

int const (*p)
const int (*p)
int const *p
const int *p

三、int*const p

那么如何声明一个自身是常量指针呢?方法是让const尽可能的靠近p,下面的这个就是

int main() {
    int a = 10;
    int b = 20;
    int* const p = &a;
    printf("%d\n",*p);
    return 0;
}

指针只能指向a,指向b就报错。地址只能赋值一次。

这里有一个简便的区分方法:沿着*号划一条线,如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量.如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。

四、const用于函数的地址传递参数

void func(const int *p);

这种形式通常用于在数组形式的参数中模拟传值调用。也就是相当于函数调用者声称:"我给你一个指向它的指针,但你不能去修它。"如果函数编写者遵循了这个约定,那么就相当于模拟了值传递。这也是const最有用之处了:用来限定函数的形参,这样该函数将不会修改实参指针所指的数据。这里注意了,是函数不应该去修改而不是不能修改,也就是说const不能阻止参数的修改(原因见上)。

加载全部内容

相关教程
猜你喜欢
用户评论