|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
在C语言关键字中const举足轻重,我们今天就深度聊一聊const的定义和实际应用,让它不再是迷。
; {0 g& p! V2 d! c5 y. T9 s8 S X$ z
C语言中const关键字是constant的缩写,是恒定不变的意思。通常翻译为常量、常数等,我们一看到const关键字马上就想到了常量。这是不精确的,精确来说应该是只读变量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容。那么const推出的初始目的正是为了取代预编译指令,消除它的缺点,同时继承它的优点。
0 z" a" D# |5 `) ^6 N9 l5 P4 I
) {% Z9 s5 v) I1 I事实上在C语言中const功能很强大,它可以修饰变量、数组、指针、函数参数等。
0 D/ K) l b2 q% g
5 {+ W' H6 g( i5 }; J3 R8 e0 ^1、const 修饰的只读变量:
% X0 t( z" q4 r# MC语言中采用const修饰变量,功能是对变量声明为只读特性,并保护变量值以防被修改。
( n- H9 Y9 Z3 m, z% x' U- _) v9 l) |3 B& S) y$ r8 y
例如:
: a: X n( ?9 v! b" Oconst int Max = 100; K* P$ O' y& i; X3 N! T
int Array[Max];
2 ~8 K/ u. W, |* W8 i. [! h& |
, \0 s9 S( Z' i; E( h' I! U5 D这个大家可以在Visual C++6.0创建一个.c文件测试一下,你会发现在.c文件中编译器会提示出错。我们知道定义一个数组必须指定其元素的个数,这也从侧面证实在C语言中const修饰的Max仍然是变量,只不过是只读属性罢了。
: |% w- p ~% B9 {/ h8 b: [" `
& r1 r5 q8 m6 O& ~' g$ k还有值得注意的是,定义变量的同时,必须初始化,并且不能再重新赋值。
6 o( X& M1 \8 c6 a5 ^- c, z3 f1 P
2、节省空间,避免不必要的内存分配,同时提高效率6 \% Q) M1 x) o5 E" i
编译器通常不为普通const只读变量分配存储空间,而是将他们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。
2 V$ g+ b6 U) T
; e5 z( G4 _9 [9 Z( x例如:) t8 j/ {* ^) P3 b
#define M 3 //宏常量
: M# I0 k& e: K0 v0 H C7 Uconst int N= 5; //此时并未将N放入内存中) s& p& |6 q; }1 R/ b
int i = N; //此时为N分配内存,以后不再分配' \; K* R; t5 J+ f
int I = M; //预编译期间进行宏替换,分配内存
1 V5 l$ a6 S% hint j = N; //没有内存分配' d% [& D9 @1 }9 _1 u4 X" _
int J = M; //再进行宏替换,又一次分配内存1 m! C: c# T5 I9 F# z0 @
% l& \$ F1 Q* nconst定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是像#define一样给出的是立即数。所以,const定义的只读变量在程序运行过程中只有一份备份(因为它是全局的只读变量,存放在静态区),而#define定义的宏常量在内存中有若干个备份。#define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。#define宏没有类型,而const修饰的只读变量具有特定的类型。7 ~5 I0 [! t# N2 W
: L- d; s' K! S$ J
3、修饰一般变量
- ~' {/ p& }9 }1 O( X一般变量是指简单类型的只读变量。这种只读变量在定义时,修饰符const可以用在类型说明符前,也可以用在类型说明符后( U- P* g( ~2 ~0 w# @ K
& i3 S, K$ X5 P7 @
例如:1 |0 V6 r2 @7 m' x1 L% I/ C& F
int const i = 2; 或 const int i = 2;
" q; R4 {3 L6 f* P; e( e; D G4 B& J9 T( z/ h- U
4、修饰数组2 E! W# y, e4 a& m" I! r* {0 W
C语言中const还可以修饰数组,举例如下:7 }( m7 D6 x+ @6 m9 h# @
const int array[5] = {1,2,3,4,5};) T$ ~8 O+ @4 r9 l+ X
array[0] = array[0]+1; //错误3 I5 h" J6 \- m- ]6 ~! {) s. f
数组元素与变量类似,具有只读属性,不能被更改;一旦更改,如程序将会报错。* j: V# Q( X" K6 p `
: O4 H# s/ `$ Z2 u0 o
5、 修饰指针( y) g4 g# c% ~0 a
C语言中const修饰指针要特别注意,共有两种形式,一种是用来限定指向空间的值不能修改;另一种是限定指针不可更改。举例说明如下:
! z0 j; ?( e) I7 T* @' a# e3 x- N i4 ~- r4 Z# o
Const离谁近修饰谁的原则
3 e& d' ^; D* Y# \
( _2 m8 a$ x; g5 h, l7 p例如:
5 s9 A" z- N! F1 C3 J8 qconst int * p1; //定义1,p1可变,p1指向的对象不可变
* k( |5 h2 E! s t% F, }3 dint * const p2; //定义2,p2不可变,p2指向的对象可变
! ?; O6 T/ S" O5 s5 ^/ E
$ k1 n- E8 S- v$ [上面定义了两个指针p1和p2。
% @( m0 C3 y c1 K+ H# o在定义1中const限定的是*p1,即其指向空间的值不可改变,若改变其指向空间的值如*p1=20,则程序会报错;但p1的值是可以改变的,对p1重新赋值如p1=&k是没有任何问题的。
8 Y0 ~! {2 ]1 Z% D在定义2中const限定的是指针p2,若改变p2的值如p2=&k,程序将会报错;但*p2,即其所指向空间的值可以改变,如*p2=80是没有问题的,程序正常执行。
0 j+ X" V# {) x$ u4 ~/ [& V6 O( U9 T& t
6、修饰函数参数
' \8 V# [' v7 B: X6 ]% W/ {' M. Mconst修饰符也可以修饰函数的参数,当不希望这个参数值在函数体内被意外改变时使用。所限定的函数参数可以是普通变量,也可以是指针变量。
. F( Q5 P2 i3 }) U/ I$ Y y0 o/ \& M' w, C# Y
举例如下:
/ I& `9 f! O1 v7 A0 J& }8 Ivoid fun1(const int i){其它语句……i++; //对i的值进行了修改,程序报错其它语句}
: ^$ o4 f+ {- f; `- b' n/ ^- y, [4 f8 K0 @5 E9 \
告诉编译器i在函数体中不能改变,从而防止了使用者的一些无意或者错误的修改。
5 r' B0 B. G1 R# I& Z
?3 X+ v \, m( O fvoid fun2(const int *p){其它语句……(*p)++; //对p指向空间的值进行了修改,程序报错其它语句}$ o+ x& C6 b8 h) M- d* v7 X6 ?$ _
' L$ L" J; i) l. m! D/ }7、修饰函数的返回值
- {, Y) z5 k4 ?Const修饰符也可以修饰函数的返回值,返回值不可被改变。/ P7 x' Z/ n) |) z# T \) ]
5 _! Q. r% `& F# z9 J; }9 RConst int Fun(void);
" g/ n! R2 B- A0 Q( g& g' s+ O+ ]* Y) _. E
6 G+ F7 z; `* H3 S
|
|