《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 可編程邏輯 > 業(yè)界動(dòng)態(tài) > 嵌入式領(lǐng)域,你要了解你的編譯器

嵌入式領(lǐng)域,你要了解你的編譯器

2015-09-18
關(guān)鍵詞: 嵌入式 編譯器

  我做嵌入式行業(yè),編程也多和硬件打交道,好多人說(shuō)編譯器只是工具,重要的在于算法和思想。這話說(shuō)的本來(lái)沒(méi)錯(cuò),但要有一個(gè)條件在先:那就是你真正掌握了你所用的編譯器。但就我來(lái)看,真正熟悉編譯器的卻并不多見(jiàn)。當(dāng)你深入了解一個(gè)編譯器后,你能像用匯編一樣用C,可以像匯編那樣隨心所欲的操作MCU!
  了解一個(gè)編譯器,首先應(yīng)該有匯編的基礎(chǔ),不要求能用匯編編寫(xiě)程序或做過(guò)項(xiàng)目,但至少看的懂!不熟悉匯編的嵌入式程序員是不合格的程序員!
  了解一個(gè)編譯器,最好的方法是看它自帶的幫助文件,至少要看過(guò)Compiler User's Guide ,至少遇到問(wèn)題會(huì)想到到幫助中查找方法,雖然幫助大多是E文。
  工作以來(lái)一直使用keil MDK編譯器,對(duì)于這個(gè)編譯器的界面以及設(shè)置,可以參考博文:http://blog.csdn.net/zhzht19861011/article/details/5964827,在這里先來(lái)看一看keil MDK編譯器的一些細(xì)節(jié),看看這些細(xì)節(jié),你知道多少。
  1. 在所有的內(nèi)部和外部標(biāo)識(shí)符中,大寫(xiě)和小寫(xiě)字符不同。
  2. 默認(rèn)情況下,char 類(lèi)型的數(shù)據(jù)項(xiàng)是無(wú)符號(hào)的。它們可以顯式地聲明為signed char 或 unsigned char。
  3.基本數(shù)據(jù)類(lèi)型的大小和對(duì)齊:
  類(lèi)型         位大小        按字節(jié)自然對(duì)齊
  char 8 1
  short 16 2
  int 32 4
  long 32 4
  long long 64 8
  float 32 4
  double 64 8
  long double 64 8
  所有指針 32 4
  bool (僅用于C++ ) 8 1
  _Bool (僅用于C ) 8 1
  wchar_t (僅用于C++ ) 16 2
  注:a. 通常局部變量保留在寄存器中,但當(dāng)局部變量太多放到棧里的時(shí)候,它們總是字對(duì)齊的。例如局部char變量在棧里以4為邊界對(duì)齊;
  b. 壓縮類(lèi)型的自然對(duì)齊方式為1。使用關(guān)鍵字__packed來(lái)壓縮特定結(jié)構(gòu),將所有有效類(lèi)型的對(duì)齊邊界設(shè)置為1.
  4. 整數(shù)以二進(jìn)制補(bǔ)碼形式表示;浮點(diǎn)量按IEEE格式存儲(chǔ)。
  5. 有符號(hào)量的右移是算術(shù)移位,即移位時(shí)要保證符號(hào)位不改變。
  6. 對(duì)于int類(lèi)的值:超過(guò)31位的左移結(jié)果為零;無(wú)符號(hào)值或正的有符號(hào)值超過(guò)31位的右移結(jié)果為零。負(fù)的有符號(hào)值移位結(jié)果為-1。
  7. 整數(shù)除法的余數(shù)的符號(hào)于被除數(shù)相同,由ISO C90標(biāo)準(zhǔn)得出;
  8. 如果整型值被截?cái)酁槎痰挠蟹?hào)整型,則通過(guò)放棄適當(dāng)數(shù)目的最高有效位來(lái)得到結(jié)果。如果原始數(shù)是太大的正或負(fù)數(shù),對(duì)于新的類(lèi)型 ,無(wú)法保證結(jié)果的符號(hào)將于原始數(shù)相同。所以強(qiáng)制類(lèi)型轉(zhuǎn)化的時(shí)候,對(duì)轉(zhuǎn)換的結(jié)果一定要清晰。
  9. 整型數(shù)超界不引發(fā)異常;像unsigned char test;       test=1000;這類(lèi)是不會(huì)報(bào)錯(cuò)的,賦值或計(jì)算時(shí)務(wù)必小心。
  10. 默認(rèn)情況下,整型數(shù)除以零返回零。
  11. 對(duì)于兩個(gè)指向相同類(lèi)型和對(duì)齊屬性的指針相減,計(jì)算結(jié)果如下表達(dá)式所示:
  ((int)a ? (int)b) / (int)sizeof(指向數(shù)據(jù)的類(lèi)型)
  12. 在嚴(yán)格C中,枚舉值必須被表示為整型,例如,必須在?2147483648 到+2147483647的范圍內(nèi)。但keil MDK自動(dòng)使用對(duì)象包含enum范圍的最小整型來(lái)實(shí)現(xiàn)(比如char類(lèi)型),除非使用編譯器命令??enum_is_int 來(lái)強(qiáng)制將enum的基礎(chǔ)類(lèi)型設(shè)為至少和整型一樣寬。超出范圍的枚舉值默認(rèn)僅產(chǎn)生警告:#66: enumeration value is out of "int" range
  13. 結(jié)構(gòu)體:struct {
  char c;
  short  s;
  int        x;
  }          //這個(gè)結(jié)構(gòu)體占8個(gè)字節(jié)
  但是,結(jié)構(gòu)體:
  struct {
  char c;
  int        x;
  short  s;
  }          //這個(gè)結(jié)構(gòu)體占12個(gè)字節(jié)
  這是為什么?
  對(duì)于結(jié)構(gòu)體填充,據(jù)定義結(jié)構(gòu)的方式,keil MDK編譯器用以下方式的一種來(lái)填充結(jié)構(gòu):
  定義為static或者extern的結(jié)構(gòu)用零填充;
  ?;蚨焉系慕Y(jié)構(gòu),例如,用 malloc() 或者 auto定義的結(jié)構(gòu),使用先前存儲(chǔ)在那些存儲(chǔ)器位置的任何內(nèi)容進(jìn)行填充。不能使用memcmp() 來(lái)比較以這種方式定義的填充結(jié)構(gòu)!
  14. 編譯器不對(duì)聲明為volatile 類(lèi)型的數(shù)據(jù)進(jìn)行優(yōu)化。  我發(fā)現(xiàn)還有不少剛?cè)腴T(mén)的嵌入式程序員從沒(méi)見(jiàn)過(guò)這個(gè)關(guān)鍵字.
  15. __nop():延時(shí)一個(gè)指令周期,編譯器絕不會(huì)優(yōu)化它。如果硬件支持NOP指令,則該句被替換為NOP指令,如果硬件不支持NOP指令,編譯器將它替換為一個(gè)等效于NOP的指令,具體指令由編譯器自己決定。
  16. 還有一些編譯器知識(shí),我放在了另外一篇博文里,《有趣的keil mdk細(xì)節(jié)》。

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無(wú)法一一聯(lián)系確認(rèn)版權(quán)者。如涉及作品內(nèi)容、版權(quán)和其它問(wèn)題,請(qǐng)及時(shí)通過(guò)電子郵件或電話通知我們,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話:010-82306118;郵箱:aet@chinaaet.com。