一、int const a / const int a
二、const int(*p)/int const(*p)
三、int*const p
四、const用于函数的地址传递参数
一、int const a / const int aint 和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 pint const (*p)
const int (*p)
int const *p
const int *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不能阻止参数的修改(原因见上)。
到此这篇关于C语言详细讲解const的用法的文章就介绍到这了,更多相关C语言const内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!