C語言之const和volatile"究極"學習


關於const的用法,如今大概前先後後應該寫了有兩篇文章,之前學習的時候,用法體會不是那麼深入,爲啥這麼說呢,由於在學習c++的時候,會發現const關鍵字有新的玩法,關於這個新的玩法,你們能夠去看最近學習總結寫的c++文章專輯。c++

1、const的用法:web

一、const只讀變量:面試

  • const修飾的變量是隻讀的,本質上仍是變量數組

  • const修飾的局部變量在棧上分配空間微信

  • const修飾的全局變量在全局數據區分配空間編輯器

  • const只在編譯期有用,在運行期沒有用函數

注:const修飾的變量不是真的常量,它只是告訴編譯器該變量不能出如今賦值符號的左邊學習

二、const全局變量的分歧:flex

  • 在現代c語言編譯器中,修改const全局變量將致使程序崩潰優化

  • 標準c語言編譯器不會將const修飾的全局變量存儲於只讀存儲區中,而是存儲於可修改的全局數據區,其值依然能夠改變

三、代碼示例:

(1)只讀變量代碼示例:

#include <stdio.h>

int main()
{
   const int a =10;
   printf("a = %d\n",a);

   a=20;
   printf("a = %d\n",a);
  
  return 0;
}

運行結果:

test.c: In function ‘main’:
test.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;
   printf("a = %d\n",a);

   *p=20;
   printf("a = %d\n",a);


  return 0;
}


運行結果:

root@txp-virtual-machine:/home/txp# ./a.out
a = 10
a = 20

註解:經過指針的方式,就可以把a的值進行修改,這也論證了「const修飾的變量是隻讀的,本質上仍是變量」這句話

(3)const修飾全局變量:

代碼版本一

#include <stdio.h>
const int b = 40;

int main()
{
   
 
   printf("b = %d\n",b);
   b=20;
   printf("b = %d\n",b);


  return 0;
}

輸出結果:

root@txp-virtual-machine:/home/txp# gcc test.c
test.c: In function ‘main’:
test.c:10:4: error: assignment of read-only variable ‘b’
    b=20;
    ^

註解:跟const修飾棧上的變量用法同樣

代碼版本二

#include <stdio.h>
const int b = 40;

int main()
{

   int *p =(int *) &b;
   printf("b = %d\n",b);

   *p=20;
   printf("b = %d\n",b);


  return 0;
}

運行結果:

root@txp-virtual-machine:/home/txp# ./a.out
b = 40
Segmentation fault (core dumped)

註解:這裏出現了段錯誤,這也驗證了咱們上面所說的「修改const全局變量將致使程序崩潰」。

同時爲了驗證「標準c語言編譯器不會將const修飾的全局變量存儲於只讀存儲區中,而是存儲於可修改的全局數據區,其值依然能夠改變」這句話,我把這段代碼放到dev c++上進行試驗:

說明:我這個版本的編譯器支持標準c語言,因此沒致使程序崩潰,可以正常運行

四、const的本質

  • c語言中的const使得變量具備只讀屬性

  • 現代c編譯器中的const將具備全局生命週期的變量存儲於只讀存儲區,不是放在全局數據區

注:const不能定義真正意義上的常量;同時這裏注意static關鍵字修飾的變量,它的生命週期和全局變量同樣。

代碼示例:

#include <stdio.h>

const int Array[5] = {0};

void fun(int *p,int v)
{
   *p=v;
}
int main()
{
    int const i =1;
    const static int j =2;
    int const array[5] = {0};

    fun((int *)&i,1);
    fun((int *)&j,2);
    fun((int *)&array[2],3);
    fun((int *)&Array[1],4);

   return 0;

}

輸出結果:

root@txp-virtual-machine:/home/txp# ./a.out
Segmentation fault (core dumped)

註解:這裏會有段錯誤,錯誤出如今const+static修飾的j變量對其進行修改,還有const修飾的全局數組。

五、const修飾函數參數和返回值

  • const修飾函數參數表示在函數體內不但願改變參數的值

  • const修飾函數返回值表示返回值不可改變,多用於返回指針的情形

在c語言中的字符串字面量存儲於只讀存儲區中,在程序中須要使用const char* 指針,例如:

const char * s = "TXP嵌入式";//字符串字面量

代碼示例:

#include <stdio.h>

const char*fun(const int i)
{
   i=8;
    return "TXP";
}
int main()
{
   const char * p=fun(0);
    printf("%s\n",p);
    p[1]='_';
    printf("%s\n",p);

    return 0;


}


輸出結果:

root@txp-virtual-machine:/home/txp# gcc test.c
test.c: In function ‘fun’:
test.c:5:4: error: assignment of read-only parameter ‘i’
    i=8;
    ^
test.c: In function ‘main’:
test.c:12:5: error: assignment of read-only location ‘*(p + 1u)’
     p[1]='_';
     ^

註解:上面這樣寫,確定有問題。

代碼進化:

#include <stdio.h>

const char*fun(const int i)
{
//   i=8;
    return "TXP";
}
int main()
{
   const char * p=fun(0);
    printf("%s\n",p);
  //  p[1]='_';
   // printf("%s\n",p);

    return 0;


}

輸出結果:

root@txp-virtual-machine:/home/txp# ./a.out
TXP

2、volatile的用法

老實說,這個關鍵字在面試題目裏面常常會出現,可是平時學習的時候,若是你沒有真正理解這其中的含義,在筆試的時候,腦殼裏面可能依稀是記得有那麼幾個結論,可是有時候吧,一緊張就把結論給忘了,也不是不可能,因此說,咋們仍是老實一點,得真正把它原理搞明白才行,這樣上來戰場就不怕了,之後寫代碼也就少一點bug。

一、volatile的經常使用結論(volatile英文本意就是易變的意思)

這裏我先給結論,而後再給一個例子,把這個例子的講明白,全部結論就都明白了。

  • volatile可理解爲「編譯器警告指示字」

  • volatile告訴編譯器必須每次去內存中取變量值

  • volatile主要修飾可能被多個線程訪問的變量

  • volatile也能夠修飾可能被未知因素更改的變量

  • volatile能夠修飾一箇中斷子程序中會訪問到的非自動變量

二、分析原理

你們可能平時在博客學習,都會發現講解編譯器優化的,而後加了volatile關鍵來修飾變量,就告訴編譯器不要去優化這個變量了,那麼這裏的優化究竟是什麼意思呢?

從字面上來理解優化兩個字,意思就是最優值(變量的值不會改變),這裏我用一個簡單代碼來講明一下:

#include <stdio.h>

int main()
{
    int a =1;//volatile int a =0;
     
    while(a)
    {
    
    }
}

說明:上面的代碼,若是變量a沒有加volatile修飾的話,編譯器就會優化它(也就是a的值一直不變),因此while就一直死循環;而後我若是加了volatile來修飾的話,編譯器就不會去優化變量a,不優化的意思就是說,變量a的值可能就會改變,while就不會一直死循環。

固然這裏爲了好理解,我說的不是很專業,沒有從寄存器和內存的角度去說。(我也不想那麼去講解,簡單理解了就行)

總之一句話:上面的結論中,volatile修飾的都是變量,變量就可能改變,不會被編譯器優化;只是說咱們上面的結論應用場景不一樣而已。

3、總結

  • const使得變量具備只讀屬性

  • const不能定義真正意義上的常量

  • const將具備全局生命週期的變量存儲於只讀存儲區

  • volatile強制編譯器減小優化,必須每次從內存中取值


好了,今天的分享就到這裏,若是文章中有錯誤或者不理解的地方,能夠交流互動,一起進步。我是txp,下期見!

本文分享自微信公衆號 - TXP嵌入式(txp1121518wo-)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索