|
关于const的用法,现在大概前前后后应该写了有两篇文章,以前学习的时候,用法体会不是那么深刻,为啥这么说呢,因为在学习c++的时候,会发现const关键字有新的玩法,关于这个新的玩法,大家可以去看最近学习总结写的c++文章专辑。 一、const的用法: 1、const只读变量:
注:const修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边 2、const全局变量的分歧:
3、代码示例: (1)只读变量代码示例: #include <stdio.h>* E8 h# J* w% aint main()7 s+ f5 I M! ~% y" x1 L7 y7 u# g { const int a =10;# M+ {% k6 o# U1 x printf("a = %d\n",a); 9 i" ~& O' B2 }6 c0 } a=20;7 Y4 d; J. u2 } V* A printf("a = %d\n",a); 7 a2 ]" r( i! Z ]' J) \ return 0;/ f; X7 [, E0 M0 i2 z# d } 运行结果: test.c: In function ‘main’:" g$ d2 G1 Q# w4 X$ U: ntest.c:8:4: error: assignment of read-only variable ‘a’, p9 t5 }! _& v9 z a=20; ^ 2 e2 v3 V4 s0 {, D 注解:显示这个结果很正常,变量a被const修饰了,它就成了只读的。 (2)如果对变量a的值进行修改: #include <stdio.h>: p. k9 R7 a- u. M; G4 |! L8 N: j$ J( Y int main() {0 O( T, h( U/ ~& F/ ^7 R& O' [ const int a =10; int *p =(int *) &a; printf("a = %d\n",a); *p=20; printf("a = %d\n",a); + ~% W8 ?7 j" D+ _6 | 2 d' Z" M* ~; U; Q9 j return 0;$ ^ j; B4 F5 S( N5 Z, L } 运行结果: root@txp-virtual-machine:/home/txp# ./a.out; G7 i9 y/ s/ t5 Ja = 10 a = 20 4 k6 X' ~" v9 S; k9 ]8 z$ l; } 注解:通过指针的方式,就能够把a的值进行修改,这也论证了“const修饰的变量是只读的,本质上还是变量”这句话 (3)const修饰全局变量: 代码版本一 #include <stdio.h>const int b = 40;& ?" @% P9 [" s3 [7 x& A 8 p4 I8 m0 d! o2 m int main() { # c* j- @# B% k9 K- X8 H" w: m . }, [3 ~+ Y+ c7 ]( c3 w* v printf("b = %d\n",b);! Z! l/ E/ e+ X8 q' ?" u1 |7 w b=20;+ c) r! c4 x7 h) d9 E: e W2 B( c printf("b = %d\n",b);# u; K$ F$ K+ {2 c6 y 2 s8 G$ ~- Z9 u" ~# r+ c# \# o # B- e5 X! j' Z4 t$ S3 E return 0;% E3 u6 j6 u. F# F }9 ~8 v: Q: O; w: e* F" _ 输出结果: root@txp-virtual-machine:/home/txp# gcc test.ctest.c: In function ‘main’:! G4 s2 P& _; L4 W! J; z9 {( J test.c:10:4: error: assignment of read-only variable ‘b’ b=20; ^ 6 O: t" m3 t) w& l$ O 注解:跟const修饰栈上的变量用法一样 代码版本二 #include <stdio.h>const int b = 40;' K+ H8 G# Z$ [7 v6 [ / y1 N0 ?7 ]9 U) N' A/ Y* [) Z int main()4 e* n S8 E' h4 r0 [ K. h) e {! a% b5 l8 `; [" L$ M 4 c8 U7 H* \+ r8 L4 { int *p =(int *) &b;' M8 C. h8 Q: e- p printf("b = %d\n",b); / e& a/ d# E6 y$ m: R0 k2 k *p=20; printf("b = %d\n",b); return 0; }" H7 k. r3 N) y! l$ C6 A; Y 2 w% N7 d5 r" t# d2 b/ y- [ 运行结果: root@txp-virtual-machine:/home/txp# ./a.out. p3 a1 o2 g7 H& U; m1 Y' {- i' ib = 40 Segmentation fault (core dumped) 7 Z: M( i1 o+ u* U 注解:这里出现了段错误,这也验证了我们上面所说的“修改const全局变量将导致程序崩溃”。 同时为了验证“标准c语言编译器不会将const修饰的全局变量存储于只读存储区中,而是存储于可修改的全局数据区,其值依然可以改变”这句话,我把这段代码放到dev c++上进行试验:
说明:我这个版本的编译器支持标准c语言,所以没导致程序崩溃,能够正常运行 4、const的本质
注:const不能定义真正意义上的常量;同时这里注意static关键字修饰的变量,它的生命周期和全局变量一样。 代码示例: #include <stdio.h>. G' [1 ~' ]* O' B5 C3 D4 T/ w8 R+ W( e/ M/ g const int Array[5] = {0}; 0 k* c- s; ]$ O9 E void fun(int *p,int v) { *p=v;' p7 @) s+ |, F! H/ H% ?: c9 @. j } int main() { int const i =1;, o- {1 U. ^9 S7 k; N1 z, }3 n const static int j =2; int const array[5] = {0}; fun((int *)&i,1); fun((int *)&j,2); fun((int *)&array[2],3);' |/ l7 R, r+ X: w% o6 S5 a fun((int *)&Array[1],4);9 c4 e, y+ W; `' l! j+ S" C7 Z1 P* } return 0; 7 Z# V9 ?0 }3 B5 U' ^7 m } 输出结果: root@txp-virtual-machine:/home/txp# ./a.out/ m- r* _* f# \, a$ `Segmentation fault (core dumped) 注解:这里会有段错误,错误出现在const+static修饰的j变量对其进行修改,还有const修饰的全局数组。 5、const修饰函数参数和返回值
在c语言中的字符串字面量存储于只读存储区中,在程序中需要使用const char* 指针,例如: const char * s = "TXP嵌入式";//字符串字面量. r* h' e) e# E代码示例: #include <stdio.h>: b6 v, S! r& H' sconst char*fun(const int i) {5 O9 Y' D) E/ t5 c i=8; return "TXP"; }$ F% C6 k& Z3 F8 u. ]9 y int main() { const char * p=fun(0); printf("%s\n",p); p[1]='_';# {; ^( B$ x& J/ G7 z printf("%s\n",p);; r8 ?6 J5 t9 i % ]8 k. K. ?: Z. k3 t return 0; }% M- S, O' b Y2 M4 j; G7 P& e 输出结果: root@txp-virtual-machine:/home/txp# gcc test.ctest.c: In function ‘fun’:" x* [4 A' J- G5 g4 O$ E9 n* M test.c:5:4: error: assignment of read-only parameter ‘i’$ @1 y: n! C' I# S& t' ^1 Y+ d1 F5 p i=8;( \4 X$ Z. i/ X: y% Q9 X ^ test.c: In function ‘main’:9 n# R6 d/ ]# I( U8 o( ~6 q test.c:12:5: error: assignment of read-only location ‘*(p + 1u)’ p[1]='_'; ^4 y9 j6 j) {' L% j, N6 L7 c: H9 y 注解:上面这样写,肯定有问题。 代码进化: #include <stdio.h>" Y& d* P1 p& v4 K. Oconst char*fun(const int i)5 y$ {$ }/ P( ^& B4 U" K" @) ` {* d4 j4 s' U- H // i=8;0 F6 k' o$ G8 v' n return "TXP"; } int main()% v' N9 e: H* `1 K {' J, j D2 }' O: V3 d. R const char * p=fun(0); printf("%s\n",p); // p[1]='_'; // printf("%s\n",p); return 0;! ~: Q4 j. ]( m) h } * W6 A3 U$ b9 X8 L7 J 输出结果: root@txp-virtual-machine:/home/txp# ./a.out5 r5 g! i5 m* k3 ?; `) `% BTXP 6 ~+ E3 g- N9 k& q5 ` 二、volatile的用法 老实说,这个关键字在面试题目里面经常会出现,但是平时学习的时候,如果你没有真正理解这其中的含义,在笔试的时候,脑袋里面可能依稀是记得有那么几个结论,但是有时候吧,一紧张就把结论给忘了,也不是不可能,所以说,咋们还是老实一点,得真正把它原理搞明白才行,这样上来战场就不怕了,以后写代码也就少一点bug。 1、volatile的常用结论(volatile英文本意就是易变的意思) 这里我先给结论,然后再给一个例子,把这个例子的讲明白,所有结论就都明白了。
2、分析原理 大家可能平时在博客学习,都会发现讲解编译器优化的,然后加了volatile关键来修饰变量,就告诉编译器不要去优化这个变量了,那么这里的优化到底是什么意思呢? 从字面上来理解优化两个字,意思就是最优值(变量的值不会改变),这里我用一个简单代码来说明一下: #include <stdio.h>- K- C4 @' e, f7 X! Qint main()5 L( \# Y' t/ M; v( g# }/ ~ { int a =1;//volatile int a =0;. q" H; J) d3 C" M! A- x3 T 5 R( i6 z D7 V9 b# S while(a) {9 B5 t$ i; t; {! | } } 说明:上面的代码,如果变量a没有加volatile修饰的话,编译器就会优化它(也就是a的值一直不变),所以while就一直死循环;然后我如果加了volatile来修饰的话,编译器就不会去优化变量a,不优化的意思就是说,变量a的值可能就会改变,while就不会一直死循环。 当然这里为了好理解,我说的不是很专业,没有从寄存器和内存的角度去说。(我也不想那么去讲解,简单理解了就行) 总之一句话:上面的结论中,volatile修饰的都是变量,变量就可能改变,不会被编译器优化;只是说我们上面的结论应用场景不同而已。 三、总结
/ i, O. I( }, U6 C0 Q' _) F8 O 好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。 ! ?* w$ s9 Q9 i( U" `: J* T |
微信公众号
手机版