C语言,有关const
前言:
以前对于这个关键字,基本没用过。只是印象比较深的是看一些比较经典的库代码,会有很多这个字。比如函数传入指针,之前真没怎么细想,以为很复杂或者麻烦,其实,完全是由于懒惰和畏惧了。
1、
典型问题如下:
C++形参为什么加入const-CSDN博客
这时非得加,不加还出错。其实就是一个常量指针。记忆方法,int* a是一个变量指针,即a是一个指针,它是变量,对a加一个const,即对指针加const,即int* const a,时指针变成常量,就表示指针常量了。这个指针不能修改。
同样,int* a表示一个变量指针,指向的也是int型变量,在int前加一个const,即const int* a,表示指针指向的值是常量,即常量指针了。
或者,按从左向右来读即可,即const读成常量,*读成指针,哪个在前先读哪个——
const int* p ——读成常量指针
int* const p ——读成指针常量
2、
还有这种:
【cosnt关键字作用--防止意外修改】_c语言防止篡改关键字-CSDN博客
意思是对的,只是写的程序不是那个意思,就不再说了哈。
直接对输入形参加const,表示这个参数在函数内只能用,不能改。这也是个很好的习惯。
这种函数入参对变量加const变为常量,在一些地方称为顶层常量,也就是只在使用的地方限定其不能修改,其本身定义或者说外部还是可以改变的。而最常见的,是直接在全局变量前面加const,也就是其值不能改,那么这是底层限定不能改了。参照上面1,此时,在指针引用(形参)的地方,则需要在形参前加const了。
3、
所以,在算法程序中,一般参数众多,对一些不能改变的参数,直接用const定义,定义时即赋值,后续不需也不能提供修改的接口或者语句。对一些可以修改的参数,在修改的接口或者语句处修改,在使用的接口中,可以使用常量指针来引用,这样就能很好的将这些参数的修改和使用分离开来。
4、
代码举例:
int sum_test_const(int* const a, int const len) {int i,sum=0;for (i = 0; i < len; i++) {sum += a[i];}return sum;
}void main() {int zhh[3] = { 1,2,3 };int len = 3;int sum = sum_test_const(zhh, len);
}
运行无误。可见,在函数形参前加const,只是限定函数内不能修改调用时这些形参对应的实参的值,但是本身并不要求传入的实参是const量,是变量都没问题。应该说,正规代码,凡是不想被调用函数修改的实参,在调用函数的形参前,都要加上const!这就是为什么看很多的大型、标准库代码,函数形参包含大量的const的原因!
5、
应该说,其实函数传参时还是很容易搞混的,上面例子,我们到底是希望传入数组a的地址不变,还是传入的数组a的值不变呢?其实是地址不变的,即,我们传入数组时,不希望函数内部把这个地址改了,这样写,是个好习惯。
但如果我们写成const int* a呢?其实也是可以的!此时就变成了a的值不变,这也是可以的,也说得过去,也是个好习惯吧!
那么,我们更加严谨、或者说苛刻——当传入地址时,不仅要求传入的地址不能变,即指针是常量,要写成* const p这种,同时,还希望指针指向的值也不变,即,常量指针,又要写成const * p这种!那么,是不是就可以写成 const * const p这种呢?是不是太奇怪了不行呢??其实,是可以的!!见下面代码:
程序到376行是没有问题的,即子函数用const * const 形式是没问题的。对于int型变量len,其实const多了一个,int const 和const int 是一回事,都表示把传入实参当成常量。但是多写了也不报错,也不报警告:
有点神奇,要说严谨点,编译器应该报个警告啥的也好啊,哈哈。
后面标红色~的语句,是提示有问题的,即编辑器在编码阶段就能发现错误,对编程来说是很好的。