浅谈c语言灵魂——指针
由于最近开学了,又要实习,还要准备考研,好几天没写了。
上次写到指针和数组,今天在看一些c的面试题发现一个很重要的东西就是const了,相信学过c的人一定会说:“const就意味着是常数了”,那只能说明你只懂皮毛了,这里推荐一篇外国大佬 Dan Saks的文章《const T vs T const》,在他的文章里完全概括了所有的用法。
下面的代码什么意思:
const int a;
int const a;
const int *a;
int const *a;
int* const a;
int const* const a ;
一般的int const和const int效果是一样的,a都是一个常数整数型的数,在这里我们只要记住int 与const 哪个放前哪个放后都是一样的,第三个a首先是一个指针其次它是一个指向常整数型的,也就是说*a是常量了,是不能被赋值的,但是a的值是可以改变的,也就是说它可以重新指向另一个地址。看下面的代码:
int i1 = 30;
int i2 = 40;
const int *a = &i1;
a = &i2; /* 注意这里,a可以在任意时候重新赋值一个新内存地址 */
i2 = 80; /* 注意看:这里不能能用*a = 80 来代替 */
printf("%d\n", *a); /* 输出是 80 */
首先const修饰的是整个a(注意不是a)。所以a是常量,不能被赋值的,即使a所指的i2是变量。
由于前面第一个和第二已经说明const和int谁在前都是一样的,所以第三个和第四个效果也是一样的,这里可能就会问了那怎么用const来修饰a呢?,注意第五个的const的位置,那你就应该明白了。
int *const a (int* const和int *const是一样的,只是风格不同)
先看下面的代码:
int i1 = 30;
int i2 = 40;
int *const a = &i1;
/* a = &i2; 注意这里,a 不能再这样重新赋值了,即不能再指向另一个新地址第4 行的注释)*/
i1 = 80; /* 想想看:这里能用 *a = 80; 来代替吗?可以,这里可以通过*a 修改 i1 的值。(第 5 行的注释)*/
/* 请自行与前面一个例子比较。 */
printf("%d", *a);/* 输出是 80 */
写到这里相信你们都懂了,a的值是不能重新被赋值的。它只能永远指向初始化时的内存地址了但是你可以通过改变*a来修改i1的值了。
所以说第五个意思 a 是一个指向整型数的常指针(也就 是说,指针指向的整型数是可以修改的,但指针是不可修改的)
与前一个例子对照一下吧!看以下的两点分析:
1)a 因为有了 const 的修饰,所以只是一个指针常量:也就是说 a 值是不可修改的(即 a 不可以重新指向 i2 这个变量了)(请看第 4 行的注释)。
2)整个*a的前面没有 const 的修饰。也就是说,*a 是变量而不是常量,所以我们可以通过*a来修改它所指内存 i1 的值(请看第 5 行的注释)。
总之一句话,这次的 a 是一个指向 int 变量类型数据的指针常量。
也就是说如果 const 修饰在*a 前,则不能改的是*a(即不能类似这样:*a=50;赋值)而不是指 a。 如果 const 是直接写在 a前,则 a不能改(即不能类似这样:a=&i;赋值)。
说完第五个了,接着的int const* const a; 最后一个意味着 a 是一个 指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可 修改的)
const的一些基本用法就这些了,最后补充一下:
1:int *pi 指针指向 const int i 常量的情况
const int i1 = 40;
int *pi;
pi = &i1; // 这样可以吗?不行,VC 下是编译错。
// const int 类型的 i1 的地址是不能赋值给指向 int 类型地址的指针 pi 的。否则 pi 岂不是能修改 i1 的值了吗!
pi = (int *) &i1; //这样可以吗?强制类型转换可是 C 所支持的。
//VC 下编译通过,但是仍不能通过 *pi = 80 来修改 i1 的值。去试试吧!看看具体的怎样。
2:const int *pi 指针指向 const int i1 的情况
const int i1=40;
const int *pi;
pi = &i1; // 两个类型相同,可以这样赋值。很显然,i1 的值无论是通过pi 还是 i1 都不能修改的。
什么还要如此看重关键字 const 呢?
1). 关键字 const 的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数 为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃 圾,你就会很快学会感谢这点多余的信息。(当然,懂得用 const 的程序员很少会留下的垃圾 让别人来清理的。)
2). 通过给优化器一些附加的信息,使用关键字 const 也许能产生更紧凑的代码。
3). 合理地使用关键字 const 可以使编译器很自然地保护那些不希望被改变的参数,防止其 被无意的代码修改。简而言之,这样可以减少 bug 的出现。