999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

嵌入式軟件設計中編寫可移植的C代碼

2010-06-22 08:18:16張喜俊
單片機與嵌入式系統應用 2010年8期
關鍵詞:定義標準

張喜俊

(中國電子科技集團公司 第四十一研究所,青島266555)

程序員都希望盡可能地重用自己的代碼,即不需要任何修改,只是簡單地重新編譯就可以在其他系統上運行。但是,處理器架構、匯編器語法、C編譯器實現、操作系統接口都會對代碼的可移植性產生不同程度的影響。首先,匯編代碼是不可移植的,例如ARM匯編語言編寫的代碼不可能直接運行在x86處理器上,這是因為ARM和x86的指令/機器碼不同。其次,雖然MASM和NASM匯編器都可以生成x86機器碼,但是由于它們的語法并不相同,因此也不能直接重用。最后,不同操作系統的系統調用/應用程序編程接口相差甚遠,也嚴重地阻礙了代碼重用。

C標準通過規定C編譯器的行為為最大化代碼重用提供了條件,但這并不等于說C代碼就是可移植的,操作系統的差異、代碼質量、以及編譯器的實現和擴展都會對可移植性產生影響。本文主要討論影響C代碼可移植性的因素,以及如何編寫可移植的C代碼。

1 C語言標準和編譯器實現

C語言標準可以看作是C語言使用者和C編譯器實現者之間的協議。如果使用者遵守標準規定的語法,而且編譯器實現了標準規定的行為,那么使用者可以得到期望的輸出。這樣,C程序員就能夠在不了解底層硬件和操作系統等細節的情況下編寫出具有指定行為的程序。

C語言標準定義了C語言的語法和語義、運行時環境、預處理器和標準庫等。為了提高C代碼的執行效率,C標準并沒有試圖定義C語言的每個實現細節,而是為編譯器實現者提供了一定的自由,由此導致了可移植性問題。

1.1 數據類型

C語言標準只是規定了每種內置數據類型的最小尺寸,而沒有定義它的確切尺寸。例如,規定int類型至少16位,但是通常為32位;long類型至少32位,但在某些系統上卻為64位。因此一定不要假設int或long具有一個特定的尺寸,否則它們會在某個時刻突然溢出。應該使用typedef類型而不是int或long類型,例如:

或者使用宏定義:

雖然這兩種方法的效果相同,但是推薦使用 typedef類型,這樣可以充分利用編譯器的靜態檢查功能。

C99標準在頭文件inttypes.h中提供了一系列固定尺寸類型,表1列出了其中的幾個。只是到目前為止支持C99標準的編譯器仍然很少,于是程序員不得不自己定義它們。

表1 C99固定尺寸類型

除了自定義的typedef類型以外,C標準也定義了一些特殊用途的typedef類型,如表2所列。在編碼過程中應該盡可能使用這些typedef類型,而不是int等。

表2 特殊的typedef類型

1.2 編譯器實現

1.2.1 編譯器行為

為了給編譯器實現者提供靈活性以生成效率更高的代碼,C標準故意定義了3種與可移植性密切相關的行為,它們分別為未指定行為、實現定義行為和未定義行為。

①未指定行為。實現者需要從標準規定的幾種選項中選擇一種,但是不必在文檔中說明所選擇的行為,例如函數調用時實參的計算次序、宏替換時預處理器連接操作符#和##的計算次序等。

該語句依賴于n在調用power之前還是之后遞增,不同的編譯器可能產生不同的結果,而下面的代碼則并不存在二義性:

②實現定義行為。實現者需要從幾種選項中選擇一種,而且必須在文檔中說明所選擇的行為。例如,char類型可能是signed char也可能是unsigned char,因此不能對char的符號性做任何假設。如果需要特定類型的char變量,則必須顯式地使用signed char或者unsigned char,但是更好的方法是使用自定義的typedef類型。編譯器實現者一般在編譯器手冊中詳細說明它的行為。以ARM公司的RealView編譯工具為例,在編譯程序和庫指南的附錄B(標準C實現方法定義)中描述了其實現定義行為。

③未定義行為。標準不對其施加任何要求,程序既可以立即崩潰,也可以好像什么事情都沒有發生過一樣繼續運行。例如,使用不可移植或錯誤的程序構造,或者使用錯誤的數據(如溢出或除數為零)。

在ISO/IEC 9899:1999文檔的附錄J(移植問題)中詳細地描述了這3種行為。顯然,任何依賴于這3種行為之一的程序本質上都是不可移植的。如果必須依賴它們,那么應該將這部分代碼隔離起來,并且在項目文檔中說明。

1.2.2 編譯器擴展

C標準允許編譯器實現者對C語言進行擴展,這在嵌入式系統編程中尤為明顯。以 RealView為例,它使用__irq將一個C函數聲明為中斷處理器,使用__asm在C函數體中嵌入一段匯編代碼,使用__packed聲明壓縮的結構體,以及支持“//”注釋等。雖然這些擴展為程序員提供了一定的便利,但是與此同時也引入了可移植性問題,這是因為不同的編譯器有不同的擴展,即使相同的擴展也極少是兼容的。

許多編譯器都提供一些編譯選項用來檢查代碼是否嚴格符合ISO標準,例如 RealView提供了-strict選項,GCC提供了-ansi選項。打開嚴格編譯選項后,如果使用了任何特定于編譯器的特性,那么編譯器將會給出相應的警告/錯誤。

2 處理器架構

2.1 字節序

在字節尋址的存儲器中,存在小端字節序和大端字節序兩種方式存儲多字節數據。大端字節序(big endian)也稱為“網絡字節序”,在最低地址處存儲最高有效字節,而小端字節序(little endian)則在最低地址處存儲最低有效字節。假設一個32位整型數據存儲在自然對齊的地址A處,如圖1所示。如果為小端格式,那么地址A處的字為0x78563412,地址A+2處的半字為0x7856;相反,如果為大端格式,那么地址A處的字為0x12345678,地址A+2處的半字為0x5678。

圖1 字節序

不同的處理器的字節序可能并不相同,例如x86使用小端字節序,PowerPC使用大端字節序,而ARM同時支持大端格式和小端格式。如果不清楚處理器的字節序,那么可以使用下面的is_big_endian函數判斷它是否為大端字節序。

一般情況下,程序員并不需要考慮處理器的字節序,但是當編寫需要在計算機間交換數據時的應用程序(特別是網絡應用程序),則需要特別關注字節序問題。例如,sockaddr_in結構體中的端口成員就要求使用網絡字節序。為了增強網絡應用程序的可移植性,定義了兩類在本地字節序和網絡字節序之間進行轉換的函數:操作32位整數的 htonl和 ntohl,以及操作16位整數的 htons和ntohs。ntoh函數將網絡字節序轉換為本機字節序,而hton函數將主機字節序轉換為網絡字節序。

Linux支持數目眾多的處理器,與處理器字節序相關的操作都定義在各自的byteorder.h中。以PowerPC處理器為例,在linux-2.6.24includeasm-powerpcyteorder.h中包含了位于linux-2.6.24includelinuxyteorder中的big_endian.h。它定義了__BIG_ENDIAN宏(表明PowerPC處理器為大端字節序),以及一些用來在本機字節序和大/小端字節序之間進行轉換的宏。例如下面的宏專門用來操作32位數:

2.2 數據對齊

對齊的目的是為了提高處理器的執行效率。不同的處理器有不同的存儲器訪問特點,Intel x86處理器允許非對齊的存儲器訪問,但是這會造成一定的性能損失,而ARM處理器進行非對齊訪問時竟然得到一個不正確的數據。為了保證可移植性,應該確保數據的對齊性,同時避免濫用指針操作以避免非對齊的存儲器訪問。對于ARM處理器,執行下面的語句后,變量l將等于奇怪的0x01040302。

如果一個C語言原生類型T的變量在存儲器中的地址為sizeof(T)的整數倍,那么稱它是自然對齊的。一般情況下,編譯器通過自然對齊所有數據類型以解決對齊問題。對C原生類型來說,這不存在任何問題;而struct類型的對齊要求與對齊要求最嚴格的成員一致,這可能導致結構體中兩個相鄰的、不同尺寸數據類型的成員之間存在填充。例如,對結構體foo來說,它的對齊要求與y一致,隨著處理器字長的不同,x和y之間可能存在1個或3個甚至7個字節的填充。

C標準在stddef.h中定義了offsetof宏,用來返回結構體成員的偏移值。為了查看成員y的偏移值可以使用下面的語句:

GCC編譯器為此提供了更多的擴展。關鍵字__alignof__返回對象的對齊需求,例如如果目標機器要求double值對齊于8字節邊界,那么__alignof__(double)返回8。關鍵字__attribute__可以用來指定變量或者結構體成員的最低對齊需求(以字節為單位),例如int x__attribute__((aligned(16)))=0;可以通知編譯器為變量x分配一個16字節對齊的地址。如果打開了-Wpadded開關,那么當結構體存在填充時,GCC編譯器還會給出警告。如果編譯器沒有提供類似GCC那樣的擴展,那么另一個常用的技巧是使用union提升較低數據類型的對齊要求。例如對于下面的聯合u,假設sizeof(int)=4,那么可以保證c也是4字節對齊的。

結 語

總之,在實踐中應該編寫符合標準的代碼,隔離與特定處理器或者操作系統相關的代碼,甚至嘗試使用不同的編譯器編譯你的代碼,只有這樣才能確保代碼的可移植性。

[1]Horton M ark.Portable C Software[M].London:Prentice Hall,1990.

[2]Jones Derek M.The New C Standard an Economic and Cultural Commentary[M].NewYork:Addison-Wesley Professional,2003.

[3]ISO/IEC 9899:1999[EB/OL].[2010-03].www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf.

[4]Brian Kernighan W.程序設計實踐[M].裘宗燕 ,譯 .北京 :機械工業出版社,2003.

[5]Harbison Samuel P,Steele Guy L.C:A Reference Manual[M].5版.北京:人民郵電出版社,2007.

[6]Stallman Richard M,the GCC Developer Community.Using the GNU Compiler Collection:For GCC version 4.4.1[EB/OL].[2010-03].http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc.pdf.

猜你喜歡
定義標準
2022 年3 月實施的工程建設標準
永遠不要用“起點”定義自己
海峽姐妹(2020年9期)2021-01-04 01:35:44
定義“風格”
忠誠的標準
當代陜西(2019年8期)2019-05-09 02:22:48
美還是丑?
你可能還在被不靠譜的對比度標準忽悠
一家之言:新標準將解決快遞業“成長中的煩惱”
專用汽車(2016年4期)2016-03-01 04:13:43
成功的定義
山東青年(2016年1期)2016-02-28 14:25:25
2015年9月新到標準清單
修辭學的重大定義
當代修辭學(2014年3期)2014-01-21 02:30:44
主站蜘蛛池模板: 九色视频一区| 久久久四虎成人永久免费网站| 免费网站成人亚洲| 黄色网页在线观看| 一级毛片a女人刺激视频免费| 国产精品久久久久久久久| 国产成年女人特黄特色大片免费| 好紧好深好大乳无码中文字幕| 免费人成黄页在线观看国产| 免费无码AV片在线观看中文| 国产av一码二码三码无码| 日日噜噜夜夜狠狠视频| 免费全部高H视频无码无遮掩| 日本伊人色综合网| 亚洲视频一区在线| 欧美亚洲一区二区三区导航| 欧美日韩午夜| 福利一区在线| 四虎永久免费地址| 欧美精品高清| 日本免费一级视频| 伊人网址在线| 国产成人一区| 日韩二区三区无| 91丝袜美腿高跟国产极品老师| 99精品国产电影| 国产呦精品一区二区三区下载| 亚洲高清中文字幕在线看不卡| 国产精品成人久久| 日韩免费毛片| 在线色国产| 偷拍久久网| 日本道综合一本久久久88| jizz国产视频| 国产亚洲精久久久久久久91| 免费av一区二区三区在线| 色妞永久免费视频| 免费一级α片在线观看| 91丝袜乱伦| 亚洲色图欧美视频| 热久久国产| 婷婷开心中文字幕| 成人毛片在线播放| 久热re国产手机在线观看| 国产精品亚洲片在线va| 国产极品美女在线| 亚洲最大福利视频网| 国产尤物jk自慰制服喷水| 91免费国产高清观看| 亚洲综合日韩精品| 一边摸一边做爽的视频17国产| 国产精品第| 伊人国产无码高清视频| 国产偷国产偷在线高清| 天堂久久久久久中文字幕| 日韩资源站| 欧美高清三区| 亚洲欧美日韩中文字幕在线| 中文字幕精品一区二区三区视频| 国产91熟女高潮一区二区| 久996视频精品免费观看| 亚洲天堂高清| 污网站免费在线观看| 日本高清免费不卡视频| 欧美成人精品高清在线下载| 99视频精品全国免费品| 国产欧美自拍视频| 午夜福利无码一区二区| 亚洲日本一本dvd高清| 国产情精品嫩草影院88av| 亚洲无限乱码一二三四区| 人妻一区二区三区无码精品一区| 久久九九热视频| 88av在线| 中文字幕在线观看日本| 亚洲av中文无码乱人伦在线r| 亚洲精品无码高潮喷水A| 五月激激激综合网色播免费| 97亚洲色综久久精品| 免费在线成人网| 欧美一级高清片欧美国产欧美| 九九精品在线观看|