|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
在C语言关键字中const举足轻重,我们今天就深度聊一聊const的定义和实际应用,让它不再是迷。4 T: r$ ^; b: |# K$ b! C, c- p
0 O6 L' D r6 t o% [# H/ y' J* HC语言中const关键字是constant的缩写,是恒定不变的意思。通常翻译为常量、常数等,我们一看到const关键字马上就想到了常量。这是不精确的,精确来说应该是只读变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。那么const推出的初始目的正是为了取代预编译指令,消除它的缺点,同时继承它的优点。
- `. `% U( z5 F& @# ^# t" P9 b& N- S
事实上在C语言中const功能很强大,它可以修饰变量、数组、指针、函数参数等。 ]# N, _2 \ b; B# r8 r' G5 f
8 T9 h+ o3 `% h( @) A# A& u1、const 修饰的只读变量:
5 c4 {+ {/ v4 |C语言中采用const修饰变量,功能是对变量声明为只读特性,并保护变量值以防被修改。; I/ c6 s" c4 a# u7 t7 W& `, Q
- j! I4 u4 l; k/ p9 I: s% o, m
例如:* Q0 L$ L. b: R: g: D( B; M1 ]( x# y
const int Max = 100;
! e" d; F! Q& d) `' W6 m! |int Array[Max];9 ?, A2 v0 D6 F0 B/ ^
- h3 ^) b: A2 ^ ?1 _- r5 H这个大家可以在Visual C++6.0创建一个.c文件测试一下,你会发现在.c文件中编译器会提示出错。我们知道定义一个数组必须指定其元素的个数,这也从侧面证实在C语言中const修饰的Max仍然是变量,只不过是只读属性罢了。, w! m& p' f8 o2 _# P: B- m( [0 L
( q7 m8 p$ t, m& v
还有值得注意的是,定义变量的同时,必须初始化,并且不能再重新赋值。% ]/ B( C$ a1 G# h6 G8 t* [
* h9 n7 t: B& O: M7 T- g
2、节省空间,避免不必要的内存分配,同时提高效率 G3 a1 ^) ]4 N% T
编译器通常不为普通const只读变量分配存储空间,而是将他们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。
$ g7 Q" ~1 x- }& Z8 p7 e& A; x3 x- s' w$ v1 [! P
例如:+ I' p) ?+ K! m% }0 S# ]6 c
#define M 3 //宏常量5 z- c9 z. J' P/ C4 o5 ~
const int N= 5; //此时并未将N放入内存中- E/ p' v+ @5 d8 N1 z
int i = N; //此时为N分配内存,以后不再分配; B# z: y0 O$ j, O
int I = M; //预编译期间进行宏替换,分配内存
i% ~6 f s- t3 ?" a% B) Pint j = N; //没有内存分配( s& Y0 C A9 W" Q
int J = M; //再进行宏替换,又一次分配内存9 H x* z2 w, W! B
; M8 u" W4 J$ k
const定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数。所以,const定义的只读变量在程序运行过程中只有一份备份(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个备份。#define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。#define宏没有类型,而const修饰的只读变量具有特定的类型。
- v( x' n% \6 [& }( m3 [7 K
# J( a+ U# ~' x6 `: J3、修饰一般变量- Q ~9 f* Z. M/ E
一般变量是指简单类型的只读变量。这种只读变量在定义时,修饰符const可以用在类型说明符前,也可以用在类型说明符后2 p7 K$ ? |- `# K" A
0 |$ G3 ?) \$ E- I, f
例如:4 w/ O* K3 a( b' E0 P
int const i = 2; 或 const int i = 2;6 ~% Q! z6 e# H o9 @/ F" k
' G9 T+ j" X) a H4、修饰数组4 T g$ g' n3 M, C! c
C语言中const还可以修饰数组,举例如下:7 [( n3 \7 f+ U. x3 e
const int array[5] = {1,2,3,4,5};
' w2 p, s2 k* B Q* s( S3 {) j% y1 Xarray[0] = array[0]+1; //错误, K+ H/ R: f8 C- i
数组元素与变量类似,具有只读属性,不能被更改;一旦更改,如程序将会报错。1 J0 n/ q* \& K) L
7 I% H( u1 F8 b+ u% Q7 X) h
5、 修饰指针
% E) m9 J4 Y! s( J3 F3 c" L) U" pC语言中const修饰指针要特别注意,共有两种形式,一种是用来限定指向空间的值不能修改;另一种是限定指针不可更改。举例说明如下:$ @2 j% r' C0 g* q. B. s! w
: a: `5 c% r' f9 v1 M8 A S. v
Const离谁近修饰谁的原则$ l4 o$ F/ C) R* s; u0 h
2 |& r, t, a% e, @9 F. j例如:. w3 z1 n; `% S1 _. ^2 D
const int * p1; //定义1,p1可变,p1指向的对象不可变
: e( O- x0 Y" t% }8 d* s! H/ @7 Pint * const p2; //定义2,p2不可变,p2指向的对象可变
) N% y" `) p9 T) \2 _2 W% p/ ]' u. y7 F P2 g8 g
上面定义了两个指针p1和p2。: `4 j3 d' s/ M) j4 c& h1 m
在定义1中const限定的是*p1,即其指向空间的值不可改变,若改变其指向空间的值如*p1=20,则程序会报错;但p1的值是可以改变的,对p1重新赋值如p1=&k是没有任何问题的。
+ ]; g" B+ h0 u" Z在定义2中const限定的是指针p2,若改变p2的值如p2=&k,程序将会报错;但*p2,即其所指向空间的值可以改变,如*p2=80是没有问题的,程序正常执行。+ t% D* _9 K: ~6 s* \3 L, o
+ a8 N; e- `8 K- |
6、修饰函数参数
3 [$ ?: S z# p; O7 n, a; B3 dconst修饰符也可以修饰函数的参数,当不希望这个参数值在函数体内被意外改变时使用。所限定的函数参数可以是普通变量,也可以是指针变量。
* t! V/ f' X* A2 I+ N' z8 n
- @! v' q! b) s; H0 \举例如下:6 O0 A( K c/ p# Q) o5 E* |% {
void fun1(const int i){其它语句……i++; //对i的值进行了修改,程序报错其它语句}& [$ U) f! p- a
' m/ s$ H1 b6 h9 E# O% N
告诉编译器i在函数体中不能改变,从而防止了使用者的一些无意或者错误的修改。& H, R5 q( m6 D# v) v4 z4 l1 A
4 X# c% A1 s# I/ \void fun2(const int *p){其它语句……(*p)++; //对p指向空间的值进行了修改,程序报错其它语句}
- U5 L1 `6 H) [7 R2 `$ O5 U
& m) U2 m$ P, s8 J5 l; r5 `9 X7、修饰函数的返回值
% l4 M- P0 B4 H) P) ^5 s3 g4 nConst修饰符也可以修饰函数的返回值,返回值不可被改变。
! ~; a4 U: c& k5 x& [8 b" K4 I: k: n( ~( r( z
Const int Fun(void);
: T+ {4 z+ M. p9 x# p& d; t1 u5 H( C: f$ @( R
, V# s Y* ^3 g" s |
|