|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
在C语言关键字中const举足轻重,我们今天就深度聊一聊const的定义和实际应用,让它不再是迷。' o5 v/ U" w% i- K* j& h
3 X4 L. K; _' W3 D& ^$ ]
C语言中const关键字是constant的缩写,是恒定不变的意思。通常翻译为常量、常数等,我们一看到const关键字马上就想到了常量。这是不精确的,精确来说应该是只读变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。那么const推出的初始目的正是为了取代预编译指令,消除它的缺点,同时继承它的优点。
' i7 W! [+ J# w( p1 c X' z {! s: O9 z$ }, Y5 b2 \
事实上在C语言中const功能很强大,它可以修饰变量、数组、指针、函数参数等。, J4 f% y7 d" O9 P
! V% X( i7 i2 F. C+ x
1、const 修饰的只读变量:% C6 p8 r* h+ Z( Y& P! V% R% t
C语言中采用const修饰变量,功能是对变量声明为只读特性,并保护变量值以防被修改。
$ @. q$ D' q8 N7 y2 _- s, }' {8 [% x6 `+ Z
例如:( `8 p$ _; ^ |
const int Max = 100;
* y% W3 P' h& ~2 [( l7 oint Array[Max];/ g+ V2 D R* t) C) R* U$ v
) H# A, e' G9 U+ p+ w
这个大家可以在Visual C++6.0创建一个.c文件测试一下,你会发现在.c文件中编译器会提示出错。我们知道定义一个数组必须指定其元素的个数,这也从侧面证实在C语言中const修饰的Max仍然是变量,只不过是只读属性罢了。
# ]; f* p0 |3 o+ S
. E& \, Z* ^7 h! l `- E还有值得注意的是,定义变量的同时,必须初始化,并且不能再重新赋值。% B" W* i5 d7 F5 b, X# M- }
8 v B' ~1 |& [8 z# z6 x
2、节省空间,避免不必要的内存分配,同时提高效率6 t/ X- r: L V2 }6 d
编译器通常不为普通const只读变量分配存储空间,而是将他们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。* m! K. T8 s: f2 o+ _5 o: B; z8 I. @2 T
5 r2 g0 s/ O0 c3 i8 H例如:/ Z$ L1 X' ^/ h2 |) c
#define M 3 //宏常量/ ~; R; R6 |- \" Q
const int N= 5; //此时并未将N放入内存中
! w0 X: a, P! O8 W% l! |& Uint i = N; //此时为N分配内存,以后不再分配
/ H5 F5 O" l7 ~$ r( l3 yint I = M; //预编译期间进行宏替换,分配内存/ B! u% r/ H) a* {
int j = N; //没有内存分配
1 B# V4 Y# e5 D4 W- ?7 w& zint J = M; //再进行宏替换,又一次分配内存! i* @/ V; Z8 F. H, k! d( _
7 @+ T+ z7 V' v
const定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数。所以,const定义的只读变量在程序运行过程中只有一份备份(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个备份。#define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。#define宏没有类型,而const修饰的只读变量具有特定的类型。
P* _0 i' \# N5 x$ R' W' [) o( A+ `& L0 d& S) D5 e; w! s
3、修饰一般变量3 V7 D5 U" X7 f+ G7 c/ Y
一般变量是指简单类型的只读变量。这种只读变量在定义时,修饰符const可以用在类型说明符前,也可以用在类型说明符后 c4 ]1 W5 Y' L0 o8 Y+ x: }: p
" x4 I: b1 F9 @/ ~" b
例如:; w5 _/ u& ^5 Z$ |6 J# s& _, i+ n, L4 s
int const i = 2; 或 const int i = 2;6 D* e4 a& B' q- Z9 y
7 I. Z4 d+ U( R
4、修饰数组 O/ ~" B# |4 P9 N& o- u$ H
C语言中const还可以修饰数组,举例如下:
, t j( G$ b8 g, ], a6 Pconst int array[5] = {1,2,3,4,5};0 [- _# t6 E2 T7 X$ o p
array[0] = array[0]+1; //错误( _9 f: v% @, U c) P- r
数组元素与变量类似,具有只读属性,不能被更改;一旦更改,如程序将会报错。3 v- j1 o9 I4 k1 M2 m% T, m2 k
0 Y) z1 X. K# v" b- P) n& f" `5、 修饰指针
5 w7 u; m" y7 P, x# k5 t# pC语言中const修饰指针要特别注意,共有两种形式,一种是用来限定指向空间的值不能修改;另一种是限定指针不可更改。举例说明如下:! g2 `& s* {9 i( l" t) l5 S$ h J# f# y
$ @2 A# S- k- k. x- K8 r& m3 M; z3 g' I
Const离谁近修饰谁的原则
: {2 H9 B; k. x0 |& T9 [. S% ?5 F$ G) F+ L. v6 {
例如:
+ ^6 [2 {1 r8 O4 y* zconst int * p1; //定义1,p1可变,p1指向的对象不可变& V- K8 R* E8 M
int * const p2; //定义2,p2不可变,p2指向的对象可变, r' r) @3 }" u; \9 @) G2 L }8 [6 L* Y
t0 z, @+ U+ Q; f# I( y上面定义了两个指针p1和p2。7 S o9 W( S: E" b: |
在定义1中const限定的是*p1,即其指向空间的值不可改变,若改变其指向空间的值如*p1=20,则程序会报错;但p1的值是可以改变的,对p1重新赋值如p1=&k是没有任何问题的。0 n2 @# w0 m$ q
在定义2中const限定的是指针p2,若改变p2的值如p2=&k,程序将会报错;但*p2,即其所指向空间的值可以改变,如*p2=80是没有问题的,程序正常执行。% @( E$ S0 r+ ~) q
1 E( ?0 r6 ?7 L# d9 y8 t
6、修饰函数参数0 [' h/ m3 Z1 k2 d- c' w& \4 l
const修饰符也可以修饰函数的参数,当不希望这个参数值在函数体内被意外改变时使用。所限定的函数参数可以是普通变量,也可以是指针变量。5 H4 l4 m" L9 J: E$ J9 D
- U$ r: K/ l& o. U$ _举例如下:
) K- h) R/ j* v, h# k( @; s5 ovoid fun1(const int i){其它语句……i++; //对i的值进行了修改,程序报错其它语句}
$ q1 Y: L. E1 u0 M7 F
$ H7 x& p; M2 K; D' W* F' J告诉编译器i在函数体中不能改变,从而防止了使用者的一些无意或者错误的修改。
: u8 ]- M5 C0 D- `. r* @$ _
" Y' Q! w2 F' o' i2 ?void fun2(const int *p){其它语句……(*p)++; //对p指向空间的值进行了修改,程序报错其它语句}
1 C" Y( z4 Z9 R" }
( \9 U/ s, X6 W( P. ]. M# c/ w# u7、修饰函数的返回值" H4 J" G. K, ]% t& W# H
Const修饰符也可以修饰函数的返回值,返回值不可被改变。
" _4 n- [" }8 t* I
* B% R. A( e" R2 f. Q4 O2 {Const int Fun(void);0 T* c2 `0 F0 `0 ~% o6 [7 K1 b) _
' O G) C! v o5 n: ]
! K4 P7 H" D9 Y0 v4 Y# x7 G3 e |
|