浅谈const关键字与指针、define、typedef混用

下面有四条声明,const修饰的到底是哪个?是a是常量还是*a是常量?由于只是关键字调换下顺序,是非常容易搞混的。我来详细说下。

1
2
3
4
const int * a = &b;
int const * a = &b;
int * const a = &b;
const int * const a = &b;

区分它们是非常简单的,只需要下面记住两条规则:

如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。
于是乎,刚才的四条声明也就容易区分了。

1
2
3
4
5
const int * a = &b; //const在*的左边 ,用来修饰a所指向的地址的值,*a为常量
int const * a = &b; //这句与上句是相同的,const在*的左边
int * const a = &b; //const在*的右边 那么const修饰的是a本身, a是常量
const int * const a = &b; //a与*a均为常量,都不能被改变
如果还是不明白,请上机测试下,分别给a和*a赋值,常量一般情况是不能被改变的(当然有特殊情况,以后再说)。

我这里再说下const与define、typedef,是否跟我们想象的那样。

1
2
3
4
5
6
7
typedef int* pint; 
#define PINT int*

int k = 5;

const pint m = &k;
const PINT n= &k;

我们用一个完整的程序(其实有错误,等下就知道了)来测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
typedef int* pint;
#define PINT int*
int k = 5;
const pint m = &k;
const PINT n= &k;
int main(void)
{
int b = 2;
*m = 3;
*n = 3;
m = &b;
n = &b;
return 0;
}

放上面的代码上去测试,我们看到编译出错了,位置是

1
*n = 3;

很明显*n是不可改变的,我们自己也可以很容易推是我出来。

1
2
3
4
#define PINT int*
int k = 5;
const PINT n= &k; //等价于const int * n = &k;
//const PINT n= &k; 被预处理为const int * n = &k;

我们接着这把*n = 3;注释掉,再编译一次,发现又出错了,错误的地方是

1
m = &b;

也就是说明指针m是常量,这倒是出乎意料了,

1
2
3
4
typedef int* pint;
int k = 5;
const pint m = &k;
const int* m = &k; //这两句竟然不是相等的!为什么呢?

其实这里很多人把typedef当成了define。
typedef不是define,typedef是别名。
我们仔细看下pint, pint是指针类型,const的指针当然是int *const

1
2
3
4
typedef int* pint;
int k = 5;
const pint m = &k; //相当于int* const m = &k;
//typedef不是宏代换,ping是个指针类型,const的指针是int *const

好了,其实const关键字与指针、define、typedef混用也不是太麻烦嘛。

坚持原创技术分享,您的支持将鼓励我继续创作!