成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C語言關鍵字應用技巧

開發 后端
volatile修飾表示變量是易變的,編譯器中的優化器在用到這個變量時必須每次都小心地從內存中重新讀取這個變量的值,而不是使用保存在寄存器里的備份,有效的防止編譯器自動優化,從而與軟件設計相符合。

 

1、volatile

volatile修飾表示變量是易變的,編譯器中的優化器在用到這個變量時必須每次都小心地從內存中重新讀取這個變量的值,而不是使用保存在寄存器里的備份,有效的防止編譯器自動優化,從而與軟件設計相符合。

中斷服務與主程序共享變量:

  1. //volatile uint8_t flag=1; 
  2. uint8_t flag=1; 
  3.  
  4. void test(void) 
  5.     while(flag) 
  6.     { 
  7.         //do something 
  8.     } 
  9.  
  10. //interrupt service routine 
  11. void isr_test(void) 
  12.     flag=0; 

如果沒使用volatile定義flag,可能在優化后test陷入死循環,因為test里使用的flag并沒修改它,開啟優化后,編譯器可能會固定從某個內存取值。例如:

  1. for(int i=0; i<100000; i++); 
  2. //對比 
  3. for(volatile int i=0; i<100000; i++); 

前者可能被優化掉,雖然編碼本意是需要執行操作延時,但編譯器認為代碼無意義。

總的來說,volatile是告知編譯器,不管代碼如何,必須保留,而且使用時需要重新從內存讀取更新,不能使用先前讀取的緩存,一般在驅動代碼中使用較多。

2、const

const是恒定不變的意思,其修飾的各種數據類似只讀效果。

1)修飾變量

采用const修飾變量,即變量聲明為只讀,保護變量值以防被修改。例如

  1. const int i = 1; 

上面這個例子表明,變量i具有只讀特性,不能夠被更改;若想對i重新賦值,如i = 10;屬于錯誤操作。

特別說明,定義變量的同時進行初始化,寫成int const i=1,是正確的。

2)修飾數組

C語言中const還可以修飾數組,舉例如下:

  1. const int array[5] = {1,2,3,4,5}; 
  2. array[0] = array[0]+1; //錯誤,array是只讀的,禁止修改 

數組元素與變量類似,具有只讀屬性,不能被更改;一旦更改,編譯時就會報錯。

使用大數組存儲固定的信息,例如查表(表驅動法的鍵值表),可以使用const節省ram。編譯器并不給普通const只讀變量分配空間,而是將它們保存到符號表中,無需讀寫內存操作,程序執行效率也會提高。

3)修飾指針

C語言中const修飾指針要特別注意,共有兩種形式,一種是用來限定指向空間的值不能修改;另一種是限定指針不可更改。舉例如下:

  1. int i = 1; 
  2. int j = 2; 
  3.  
  4. const int *p1 = &i; 
  5. int* const p2 = &j; 

上面定義了兩個指針p1和p2,區別是const后面是指針本身還是指向的內容。

在定義1中const限定的是* p1,即其指向空間的值不可改變,若改變其指向空間的值如* p1=10,則程序會報錯;但p1的值是可以改變的,對p1重新賦值如p1=&k是沒有任何問題的。

在定義2中const限定的是指針p2,若改變p2的值如p2=&k,程序將會報錯;但* p2,即其所指向空間的值可以改變,如* p2=20是沒有問題的,程序正常執行。

4)修飾函數參數

const關鍵字修飾函數參數,對參數起限定作用,防止其在函數內部被修改。所限定的函數參數可以是普通變量,也可以是指針變量。例如:

  1. void fun(const int i) 
  2.     …… 
  3.     i++; //對i的值進行了修改,程序報錯 

常用的函數如strlen

  1. size_t strlen(const char *string); 

const在庫函數中使用非常普遍,是一種自我保護的安全編碼思維。

3、struct與union

對于struct 結構體和union共聯體在嵌入式領域是使用得非常頻繁的,一些可編程芯片提供的寄存器庫都是采用結構體和共聯體結合的方式來提供給軟件人員進行開發,同時在平時的編碼過程中這兩個數據類型的靈活應用也能夠實現代碼更好的封裝與簡化。

如下面的簡單示例,就可以非常靈活的訪問Val中的bit位。

  1.  typedef union 
  2.  { 
  3.      BYTE Val; 
  4.      struct __packed 
  5.      { 
  6.         BYTE b0:1; 
  7.         BYTE b1:1; 
  8.         BYTE b2:1; 
  9.         BYTE b3:1; 
  10.         BYTE b4:1; 
  11.         BYTE b5:1; 
  12.         BYTE b6:1; 
  13.         BYTE b7:1; 
  14.     } bits; 
  15. }BYTE_VAL, BYTE_BITS; 

其中:1表示按位操作。不只是位-字節可以,單字節與多字節也可以簡化拼接。

  1. #include "stdio.h" 
  2.  
  3. typedef struct 
  4.     union 
  5.     { 
  6.         struct 
  7.         { 
  8.             unsigned char low; 
  9.             unsigned char high; 
  10.         }; 
  11.         unsigned short result; 
  12.     }; 
  13. }test_t; 
  14.  
  15.  
  16. int main(int argc, char *argv[]) 
  17.     test_t hello; 
  18.  
  19.     hello.high=0x12; 
  20.     hello.low=0x34; 
  21.  
  22.     printf("result=%04X\r\n",hello.result);//輸出 result=1234  
  23.  
  24.     return 0; 

運行輸出 result=1234 (win7系統下QT開發環境),原本需要 (high<<8)|low 運算,可以簡化為共用體類型自動完成,但必須注意平臺的字節順序,屬于大端還是小端模式。

在應用層面,如果明確某個數據可能存在兩種可能,而且兩種結果不會同時存在,也可以使用結構體與共用體組合的方式,確保模塊對外接口統一。

例如移動通信模塊,使用數據結構保存其基站信息,因為制式不同,模塊可能工作在2G-GSM,也可能在4G-Cat1,為保證上層讀取基站信息接口唯一,使用共用體就非常合適,否則需定義兩套接口。如果覺得文章可以,可關注微信公眾號【嵌入式系統】獲取更多信息。

4、預定義標識符

一般編譯器都支持預定義標識符,這些標識符結合printf等打印信息幫助程序員調試程序是非常有用的,一般編譯器會自動根據用戶指定完成替換和處理。

部分標識:

  1. __FILE__    //表示編譯的源文件名 
  2. __LINE__   //表示當前文件的行號 
  3. __FUNCTION__  //表示函數名 
  4. __DATE__  //表示編譯日期 
  5. __TIME__   //表示編譯時間 

使用范例:

  1. printf("file:%s,line:%d,date:%s,time:%s",__FILE__,__LINE__,__DATE__,__TIME__); 

這些比較常見,主要用于日志分析、版本記錄,便于調試。

5、#與##

#:是一種運算符,用于帶參宏的文本替換,將跟在后面的參數轉成一個字符串常量。

##:是一種運算符,是將兩個運算對象連接在一起,也只能出現在帶參宏定義的文本替換中。

  1. #include "stdio.h" 
  2.  
  3. #define TO_STR(s) #s 
  4. #define COMB(str1,str2) str1##str2 
  5.  
  6. int main(int argc, char *argv[]) 
  7.     int UART0= 115200; 
  8.  
  9.     printf("UART0=%d\n", COMB(UART, 0));//字符串合并為變量UART0 
  10.     printf("%s\n", TO_STR(3.14));//將數字變成字符串 
  11.  
  12.     return 0; 

6、void 與 void*

void表示的是無類型,不能聲明變量或常量,但是可以把指針定義為void類型,如void* ptr。void* 指針可以指向任意類型的數據,在C語言指針操作中,任意類型的數據地址都可轉為void* 指針。因為指針本質上都是unsigned int。

常用的內存塊操作庫函數:

  1. void * memcpy( void *dest, const void *src, size_t len ); 
  2. void * memset( void *buffer, int c, size_t num); 

數據指針為void* 類型,對傳入任意類型數據的指針都可以操作。另外其中memcpy第二個參數,const現在也如前文所述,拷貝時對傳入的原數據內容禁止修改。

特殊說明,指針是不能使用sizeof求內容大小的,在ARM系統固定為int 4字節。對于函數無輸入參數的,也盡量加上void,如

  1. void fun(void); 

7、weak

一般簡化定義

  1. #define _WEAK __attribute__((weak))   

函數名稱前面加上__WEAK屬性修飾符稱為“弱函數”,類似C++的虛函數。鏈接時優先鏈接為非weak定義的函數,如果找不到則再鏈接帶weak函數。

  1. _WEAK void fun(void)   
  2. {   
  3.     //do this 
  4. }   
  5.  
  6. //不在同一個.c,兩同名函數不能在同一個文件 
  7. void fun(void)   
  8. {   
  9.     //do that 
  10. }   

這種自動選擇的機制,在代碼移植和多模塊配合工作的場景下應用較多。例如前期移植代碼,需要調用某個接口fun,但當前該接口不存在或者未移植完整使用,可以使用weak關鍵字定義為空函數先保證編譯正常。后續移植完成實現了fun,即軟件中有2個fun函數沒有任何錯誤,編譯器自動會識別使用后者。當然也粗暴的#if 0屏蔽對fun的調用,但要確保后續記得放開。

8、總結

存在即合理,C語言里面的關鍵字,每個都有其特殊的意義,只是一般使用較少,譬如作文,使用常用的漢字可以;但引經據典,使用特殊的修飾辭藻更能顯出水平。后續對section 進行詳細說明,它和動態加載(OTA)、接口自啟動相關。

本文轉載自微信公眾號「嵌入式系統」,可以通過以下二維碼關注。轉載本文請聯系嵌入式系統公眾號。

 

責任編輯:武曉燕 來源: 嵌入式系統
相關推薦

2009-06-29 12:58:47

This關鍵字java

2010-02-02 14:27:54

C++ static關

2010-02-05 15:51:06

C++ explici

2009-09-02 09:24:03

C# this關鍵字

2009-08-21 14:58:56

C# this關鍵字

2011-06-24 17:39:08

長尾關鍵詞

2009-08-13 13:04:29

C# lock關鍵字

2009-08-06 17:52:23

C#增加that關鍵字

2009-08-13 17:44:34

C# using關鍵字

2009-08-26 15:16:29

C# lock關鍵字

2011-06-14 13:26:27

volatile

2009-08-21 14:47:59

C# base關鍵字

2011-05-17 13:04:20

Cconst

2010-02-01 13:19:09

C++ explici

2015-11-10 16:10:22

C語言StaticConst

2011-07-14 23:14:42

C++static

2023-11-19 22:52:42

2011-06-21 09:50:51

volatile

2009-08-21 14:16:35

C# New關鍵字

2010-01-26 14:35:11

C++關鍵字
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 奇米视频777| 精品视频一区二区三区在线观看 | 亚洲欧洲日韩 | 成人欧美一区二区三区在线播放 | 中文字幕一区二区在线观看 | 日日操天天射 | 中文字幕 在线观看 | 午夜免费视频 | 国产精品成人一区二区三区夜夜夜 | 亚洲欧美一区二区三区国产精品 | 久久精品国产亚洲夜色av网站 | 日本大片在线播放 | 成人一区二区三区在线观看 | 国产精品成人久久久久 | 中文字幕高清一区 | www.黄色网 | 婷婷在线免费 | 国产视频一区二区在线观看 | 成人福利在线 | 一本一道久久a久久精品综合 | 欧美日韩成人在线 | 欧美三级在线 | 欧美一区二区三区在线看 | 亚洲欧美日韩在线不卡 | 国产成人精品一区二区三区四区 | 国产日韩欧美一区二区 | 黄色毛片在线播放 | 亚洲一区成人 | 538在线精品 | 欧美精品综合在线 | 男女视频免费 | 中文字幕在线观看一区二区 | 91p在线观看| 狠狠草视频 | 久久激情五月丁香伊人 | 精品福利在线 | 色一级片| 国产精品欧美一区二区三区 | 久久久久久www | 日本三级电影在线免费观看 | 天堂视频中文在线 |