|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
在C语言关键字中const举足轻重,我们今天就深度聊一聊const的定义和实际应用,让它不再是迷。) I9 b2 u3 f% _1 B/ k& p" T3 W
5 T% a5 S9 Q4 E: M+ @2 O# a2 E) dC语言中const关键字是constant的缩写,是恒定不变的意思。通常翻译为常量、常数等,我们一看到const关键字马上就想到了常量。这是不精确的,精确来说应该是只读变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。那么const推出的初始目的正是为了取代预编译指令,消除它的缺点,同时继承它的优点。
: E t& X9 v) `$ n. I4 ? J" I( i+ ?: s: T+ J
事实上在C语言中const功能很强大,它可以修饰变量、数组、指针、函数参数等。$ R U" Q2 ^" ~6 T; V4 y. q$ x: o
% L3 {$ h5 B% s1、const 修饰的只读变量:2 w3 b( e! i D" T7 F/ {
C语言中采用const修饰变量,功能是对变量声明为只读特性,并保护变量值以防被修改。* c M) a' g3 |* B5 P
7 k l6 r; x+ D% b9 T: E
例如:4 g7 H" L m0 N b
const int Max = 100;, u H/ S. ^+ G3 ?# h+ T$ B
int Array[Max];, K$ h' t1 ?2 j0 d# n# {6 _" E+ w
. Y. k' a( u# W+ \" R3 \
这个大家可以在Visual C++6.0创建一个.c文件测试一下,你会发现在.c文件中编译器会提示出错。我们知道定义一个数组必须指定其元素的个数,这也从侧面证实在C语言中const修饰的Max仍然是变量,只不过是只读属性罢了。0 i8 Z( Q. u* ?. \
7 Q9 z+ Q% d6 g7 B) l5 Q0 d还有值得注意的是,定义变量的同时,必须初始化,并且不能再重新赋值。3 Q& P# r+ v1 l
) p: \9 ?6 c4 o* O, A1 ~) V$ \2、节省空间,避免不必要的内存分配,同时提高效率
2 {4 t0 |% U' E) |5 |编译器通常不为普通const只读变量分配存储空间,而是将他们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。6 I0 Q9 w" [ _5 v' w8 l/ g4 Y
" ^+ o( ^2 P0 J, b. g; w
例如: ~4 K( R9 L! s5 p: r3 V" B3 l; C3 X
#define M 3 //宏常量
. A- O! P* K7 n+ Tconst int N= 5; //此时并未将N放入内存中
0 f% U& E8 T& H. L8 _. ~int i = N; //此时为N分配内存,以后不再分配) L: F+ \5 O: h9 c9 t# V8 z3 V
int I = M; //预编译期间进行宏替换,分配内存, ~) A& {3 A4 P; l) q! D$ i" s
int j = N; //没有内存分配
, g4 c$ |) p7 i5 M [1 yint J = M; //再进行宏替换,又一次分配内存 i1 Y+ x4 V) U% K
- D! a/ U- l& aconst定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数。所以,const定义的只读变量在程序运行过程中只有一份备份(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个备份。#define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。#define宏没有类型,而const修饰的只读变量具有特定的类型。
: }; N+ I& t. j0 k; E
' p/ s: s$ \4 h5 t3、修饰一般变量* k! M3 s# ]% g) N4 ^6 m7 c& v
一般变量是指简单类型的只读变量。这种只读变量在定义时,修饰符const可以用在类型说明符前,也可以用在类型说明符后7 Z3 u3 j) e D+ @ m
: p; v' Y* g5 B7 M" d9 {例如:
- k$ Y6 b3 w: W9 q" Iint const i = 2; 或 const int i = 2;
7 H( Y( b$ a9 I1 H: v. g, _$ b. V, H7 m
4、修饰数组
" L6 Y7 t; Q. v) l9 nC语言中const还可以修饰数组,举例如下:
4 z* A/ r* M6 ]8 e6 o" d& I8 F. ^% M8 @const int array[5] = {1,2,3,4,5};& f7 V# \; V8 ~- T- w7 X& l
array[0] = array[0]+1; //错误
) D( B; @7 S$ S! H数组元素与变量类似,具有只读属性,不能被更改;一旦更改,如程序将会报错。& Q) D. v% ^1 A) S
1 r+ }8 D: @5 z- o
5、 修饰指针
* h1 R8 b6 }: iC语言中const修饰指针要特别注意,共有两种形式,一种是用来限定指向空间的值不能修改;另一种是限定指针不可更改。举例说明如下:) c1 c8 t3 g- B8 N
" t4 F; ^$ m6 i0 ^/ l/ r
Const离谁近修饰谁的原则
]: V4 O! g- }, B2 |1 y9 o5 X+ _/ }/ \& D8 z! r/ n5 e
例如:! X. o7 ^7 W# D! j* V* j% A
const int * p1; //定义1,p1可变,p1指向的对象不可变5 r5 }' u- U0 S5 X9 D5 {+ c
int * const p2; //定义2,p2不可变,p2指向的对象可变- Y! t% R- }- y% r! T. |; a
. b4 c* t0 e; B+ g, K' c, D3 i! W上面定义了两个指针p1和p2。
& O, \& K8 E. k- B5 P! v在定义1中const限定的是*p1,即其指向空间的值不可改变,若改变其指向空间的值如*p1=20,则程序会报错;但p1的值是可以改变的,对p1重新赋值如p1=&k是没有任何问题的。
5 w3 ]/ U& D8 D& N8 x( a在定义2中const限定的是指针p2,若改变p2的值如p2=&k,程序将会报错;但*p2,即其所指向空间的值可以改变,如*p2=80是没有问题的,程序正常执行。
3 a+ f$ j4 z* G+ ~/ X+ q$ h' a8 w) K, ]) A8 @6 {5 t
6、修饰函数参数
( W5 a$ c" k W8 Nconst修饰符也可以修饰函数的参数,当不希望这个参数值在函数体内被意外改变时使用。所限定的函数参数可以是普通变量,也可以是指针变量。% u6 D j4 G* q9 r1 N! K; Z/ S
1 A3 P8 F4 N8 i0 r8 l9 g
举例如下:
& n8 t- k* a" d, B7 [void fun1(const int i){其它语句……i++; //对i的值进行了修改,程序报错其它语句}5 l5 k8 K3 z1 T0 }* O% u2 [: C$ j
5 F6 L' C5 w5 V: r告诉编译器i在函数体中不能改变,从而防止了使用者的一些无意或者错误的修改。
4 B: q/ Z" J8 H% M! i( H
5 t# E6 n6 l- tvoid fun2(const int *p){其它语句……(*p)++; //对p指向空间的值进行了修改,程序报错其它语句}) ^: L* d% t1 J% `- }6 i* l
4 M6 A3 T. K0 X/ @* y- V7、修饰函数的返回值
( Y3 z" f4 Z+ b) J% n" g7 R! s+ |Const修饰符也可以修饰函数的返回值,返回值不可被改变。; z7 F- f) E" O5 N9 _2 m
8 O' B2 U7 k W F3 U- SConst int Fun(void);
5 [2 T- x8 n0 p1 M1 y p0 Y$ j& S9 I0 X* |) M0 S
3 |) Q) x+ [$ K% a( p |
|