|
关于const的用法,现在大概前前后后应该写了有两篇文章,以前学习的时候,用法体会不是那么深刻,为啥这么说呢,因为在学习c++的时候,会发现const关键字有新的玩法,关于这个新的玩法,大家可以去看最近学习总结写的c++文章专辑。 一、const的用法: 1、const只读变量:
注:const修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边 2、const全局变量的分歧:
3、代码示例: (1)只读变量代码示例: #include <stdio.h>int main() {; w7 |. X" H% \5 g const int a =10;: q5 H# i. e% v- B* ] printf("a = %d\n",a); : E! C7 H# m$ ^5 t# ?8 Z a=20;6 \2 d# @4 K8 J' `! n printf("a = %d\n",a);/ [1 N& N) e Q7 ] return 0; ]5 n' a4 @; o8 m! c9 {/ X& n } & \& @( R: W- l8 d2 Z" N 运行结果: test.c: In function ‘main’:5 [8 L3 E V$ R+ utest.c:8:4: error: assignment of read-only variable ‘a’ a=20; ^ 注解:显示这个结果很正常,变量a被const修饰了,它就成了只读的。 (2)如果对变量a的值进行修改: #include <stdio.h>int main() { const int a =10; int *p =(int *) &a;: e( z8 ~% A3 t u( b printf("a = %d\n",a);4 \- C% g' b0 u9 l- N 7 ^, N3 ^4 f' i& a5 C# A *p=20;5 V: W/ s; s5 S! c* s printf("a = %d\n",a);, g3 D7 f# f( r0 W return 0; }+ O" @ e- z2 o. Z ! X) f+ a6 X9 x( S: e8 E! Z 运行结果: root@txp-virtual-machine:/home/txp# ./a.out+ A' K' [6 Q# {$ e |, E! na = 10 a = 20 注解:通过指针的方式,就能够把a的值进行修改,这也论证了“const修饰的变量是只读的,本质上还是变量”这句话 (3)const修饰全局变量: 代码版本一 #include <stdio.h>; X7 E0 j) V% c( O! b; wconst int b = 40;' s! i3 l2 B4 H9 t1 h) } int main() { ( J0 Q$ @8 x/ U- r) G printf("b = %d\n",b);6 P7 q' Q; p5 c0 v b=20; [8 t7 S. \! v" F, Z$ E5 _ printf("b = %d\n",b); 2 p( a2 x, H# r7 a3 k d7 u return 0; } X4 H# B' F* t6 p' _1 P 输出结果: root@txp-virtual-machine:/home/txp# gcc test.ctest.c: In function ‘main’:, s3 j+ M: ]8 e test.c:10:4: error: assignment of read-only variable ‘b’ b=20;: d8 B+ c) B; Z+ F# \) A ^0 \ [9 x. y" V3 C( w6 L 注解:跟const修饰栈上的变量用法一样 代码版本二 #include <stdio.h>! i& ^" l% Y0 a% R1 p7 a2 d0 z! F% t' Vconst int b = 40; int main()+ H& t7 }7 ?* S8 j {7 n0 }' I) Q( }! V' O a/ Z: h: K% p int *p =(int *) &b;9 |2 y X. I- ~2 t) |, T printf("b = %d\n",b); *p=20;$ [6 R0 N( t2 p printf("b = %d\n",b); " w: N' R2 q; R9 U, V, s# m & m& Z6 N$ c' x$ }7 x return 0; }3 p2 \! L6 H2 Z 6 z2 Q6 H7 i- `4 C S: a" V 运行结果: root@txp-virtual-machine:/home/txp# ./a.outb = 401 m" b( Q3 U& a4 T' d4 u Segmentation fault (core dumped) 6 R+ u* I: P$ s6 {! V) P 注解:这里出现了段错误,这也验证了我们上面所说的“修改const全局变量将导致程序崩溃”。 同时为了验证“标准c语言编译器不会将const修饰的全局变量存储于只读存储区中,而是存储于可修改的全局数据区,其值依然可以改变”这句话,我把这段代码放到dev c++上进行试验:
说明:我这个版本的编译器支持标准c语言,所以没导致程序崩溃,能够正常运行 4、const的本质
注:const不能定义真正意义上的常量;同时这里注意static关键字修饰的变量,它的生命周期和全局变量一样。 代码示例: #include <stdio.h>7 e8 g9 e( Q9 r( e5 l Z( p- H; T/ f4 @8 K8 n* _4 {$ h' { const int Array[5] = {0}; 8 s h" s' E8 N4 H# S: z- u void fun(int *p,int v) { *p=v;2 t f& ]8 B' v, P7 U } int main()6 E. Y. }+ m" n) R- ~ { int const i =1; const static int j =2; int const array[5] = {0};7 a4 W: z+ F! |: T5 C4 c- [ " z( Q8 W/ i* o, |1 s9 [# l fun((int *)&i,1);. Q! U: T$ q3 e+ m- n1 s% W, q fun((int *)&j,2);% t0 J1 l* P. V9 b; ~ fun((int *)&array[2],3);( x! r+ k f9 \ M" B; P3 I" d S fun((int *)&Array[1],4);& T) H/ i4 S; h: T: n* v 3 D, O1 P% k/ v4 |# S# ]4 a3 ? return 0;0 I$ I: R) c& | W) z1 Y } 输出结果: root@txp-virtual-machine:/home/txp# ./a.outSegmentation fault (core dumped) ; c, O$ Q/ p: U u7 l 注解:这里会有段错误,错误出现在const+static修饰的j变量对其进行修改,还有const修饰的全局数组。 5、const修饰函数参数和返回值
在c语言中的字符串字面量存储于只读存储区中,在程序中需要使用const char* 指针,例如: const char * s = "TXP嵌入式";//字符串字面量0 x- y5 X+ c' |. J: G! s( \代码示例: #include <stdio.h>const char*fun(const int i) { i=8; return "TXP"; } int main() { const char * p=fun(0);! j: o: L4 w7 _& p3 X7 O) i. ^ printf("%s\n",p); p[1]='_';6 L) q0 g) Q2 j6 y" ~% ? printf("%s\n",p); return 0; 2 F1 m1 x" k+ O5 B }9 w B: b A: ? , J$ Z R) J: ?( g1 ~ & ]8 g2 u1 ?; J! z ?: |0 ~8 ] 输出结果: root@txp-virtual-machine:/home/txp# gcc test.c4 O. ~- }: c! j+ J4 O+ ztest.c: In function ‘fun’:: O9 c H8 }$ `* G test.c:5:4: error: assignment of read-only parameter ‘i’- o. A) f2 S* n1 ^ i=8; ^ test.c: In function ‘main’:& Q* A o C W test.c:12:5: error: assignment of read-only location ‘*(p + 1u)’ p[1]='_'; ^ 注解:上面这样写,肯定有问题。 代码进化: #include <stdio.h>0 x$ u0 i, i1 ?5 a+ N const char*fun(const int i) { // i=8;0 T0 s1 B; }8 ~4 z return "TXP";3 w8 Z2 [" h! ^, r1 z5 z9 m( H1 A }& y2 |- Y* U' N% A$ f8 ^ int main()7 {# u3 y6 L, |5 ?* G9 ~ { const char * p=fun(0);+ c! Y, @2 s* b printf("%s\n",p);9 V P0 G- D* [/ f# N( A; w. ]* L // p[1]='_';* V4 w# s( `% Q( Y8 @ // printf("%s\n",p);2 o: ]/ c* j p3 N0 F return 0;* s# g% c: f5 O1 k # g1 [ Y! `* \, ] m) J4 F: b }) r, J. F- M5 X4 C0 W( ]8 s' `5 n$ ? 输出结果: root@txp-virtual-machine:/home/txp# ./a.outTXP% g0 R+ N: q5 z. x 二、volatile的用法 老实说,这个关键字在面试题目里面经常会出现,但是平时学习的时候,如果你没有真正理解这其中的含义,在笔试的时候,脑袋里面可能依稀是记得有那么几个结论,但是有时候吧,一紧张就把结论给忘了,也不是不可能,所以说,咋们还是老实一点,得真正把它原理搞明白才行,这样上来战场就不怕了,以后写代码也就少一点bug。 1、volatile的常用结论(volatile英文本意就是易变的意思) 这里我先给结论,然后再给一个例子,把这个例子的讲明白,所有结论就都明白了。
2、分析原理 大家可能平时在博客学习,都会发现讲解编译器优化的,然后加了volatile关键来修饰变量,就告诉编译器不要去优化这个变量了,那么这里的优化到底是什么意思呢? 从字面上来理解优化两个字,意思就是最优值(变量的值不会改变),这里我用一个简单代码来说明一下: #include <stdio.h>int main()7 O! R% l: a$ i8 b+ b4 O4 z: S9 i0 ` { int a =1;//volatile int a =0; while(a) { } } 说明:上面的代码,如果变量a没有加volatile修饰的话,编译器就会优化它(也就是a的值一直不变),所以while就一直死循环;然后我如果加了volatile来修饰的话,编译器就不会去优化变量a,不优化的意思就是说,变量a的值可能就会改变,while就不会一直死循环。 当然这里为了好理解,我说的不是很专业,没有从寄存器和内存的角度去说。(我也不想那么去讲解,简单理解了就行) 总之一句话:上面的结论中,volatile修饰的都是变量,变量就可能改变,不会被编译器优化;只是说我们上面的结论应用场景不同而已。 三、总结
好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。 |
微信公众号
手机版