亚洲免费av电影一区二区三区,日韩爱爱视频,51精品视频一区二区三区,91视频爱爱,日韩欧美在线播放视频,中文字幕少妇AV,亚洲电影中文字幕,久久久久亚洲av成人网址,久久综合视频网站,国产在线不卡免费播放

        ?

        嵌入式軟件設(shè)計(jì)中編寫可移植的C代碼

        2010-06-22 08:18:16張喜俊
        關(guān)鍵詞:小端編譯器字節(jié)

        張喜俊

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

        程序員都希望盡可能地重用自己的代碼,即不需要任何修改,只是簡單地重新編譯就可以在其他系統(tǒng)上運(yùn)行。但是,處理器架構(gòu)、匯編器語法、C編譯器實(shí)現(xiàn)、操作系統(tǒng)接口都會(huì)對代碼的可移植性產(chǎn)生不同程度的影響。首先,匯編代碼是不可移植的,例如ARM匯編語言編寫的代碼不可能直接運(yùn)行在x86處理器上,這是因?yàn)锳RM和x86的指令/機(jī)器碼不同。其次,雖然MASM和NASM匯編器都可以生成x86機(jī)器碼,但是由于它們的語法并不相同,因此也不能直接重用。最后,不同操作系統(tǒng)的系統(tǒng)調(diào)用/應(yīng)用程序編程接口相差甚遠(yuǎn),也嚴(yán)重地阻礙了代碼重用。

        C標(biāo)準(zhǔn)通過規(guī)定C編譯器的行為為最大化代碼重用提供了條件,但這并不等于說C代碼就是可移植的,操作系統(tǒng)的差異、代碼質(zhì)量、以及編譯器的實(shí)現(xiàn)和擴(kuò)展都會(huì)對可移植性產(chǎn)生影響。本文主要討論影響C代碼可移植性的因素,以及如何編寫可移植的C代碼。

        1 C語言標(biāo)準(zhǔn)和編譯器實(shí)現(xiàn)

        C語言標(biāo)準(zhǔn)可以看作是C語言使用者和C編譯器實(shí)現(xiàn)者之間的協(xié)議。如果使用者遵守標(biāo)準(zhǔn)規(guī)定的語法,而且編譯器實(shí)現(xiàn)了標(biāo)準(zhǔn)規(guī)定的行為,那么使用者可以得到期望的輸出。這樣,C程序員就能夠在不了解底層硬件和操作系統(tǒng)等細(xì)節(jié)的情況下編寫出具有指定行為的程序。

        C語言標(biāo)準(zhǔn)定義了C語言的語法和語義、運(yùn)行時(shí)環(huán)境、預(yù)處理器和標(biāo)準(zhǔn)庫等。為了提高C代碼的執(zhí)行效率,C標(biāo)準(zhǔn)并沒有試圖定義C語言的每個(gè)實(shí)現(xiàn)細(xì)節(jié),而是為編譯器實(shí)現(xiàn)者提供了一定的自由,由此導(dǎo)致了可移植性問題。

        1.1 數(shù)據(jù)類型

        C語言標(biāo)準(zhǔn)只是規(guī)定了每種內(nèi)置數(shù)據(jù)類型的最小尺寸,而沒有定義它的確切尺寸。例如,規(guī)定int類型至少16位,但是通常為32位;long類型至少32位,但在某些系統(tǒng)上卻為64位。因此一定不要假設(shè)int或long具有一個(gè)特定的尺寸,否則它們會(huì)在某個(gè)時(shí)刻突然溢出。應(yīng)該使用typedef類型而不是int或long類型,例如:

        或者使用宏定義:

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

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

        表1 C99固定尺寸類型

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

        表2 特殊的typedef類型

        1.2 編譯器實(shí)現(xiàn)

        1.2.1 編譯器行為

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

        ①未指定行為。實(shí)現(xiàn)者需要從標(biāo)準(zhǔn)規(guī)定的幾種選項(xiàng)中選擇一種,但是不必在文檔中說明所選擇的行為,例如函數(shù)調(diào)用時(shí)實(shí)參的計(jì)算次序、宏替換時(shí)預(yù)處理器連接操作符#和##的計(jì)算次序等。

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

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

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

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

        1.2.2 編譯器擴(kuò)展

        C標(biāo)準(zhǔn)允許編譯器實(shí)現(xiàn)者對C語言進(jìn)行擴(kuò)展,這在嵌入式系統(tǒng)編程中尤為明顯。以 RealView為例,它使用__irq將一個(gè)C函數(shù)聲明為中斷處理器,使用__asm在C函數(shù)體中嵌入一段匯編代碼,使用__packed聲明壓縮的結(jié)構(gòu)體,以及支持“//”注釋等。雖然這些擴(kuò)展為程序員提供了一定的便利,但是與此同時(shí)也引入了可移植性問題,這是因?yàn)椴煌木幾g器有不同的擴(kuò)展,即使相同的擴(kuò)展也極少是兼容的。

        許多編譯器都提供一些編譯選項(xiàng)用來檢查代碼是否嚴(yán)格符合ISO標(biāo)準(zhǔn),例如 RealView提供了-strict選項(xiàng),GCC提供了-ansi選項(xiàng)。打開嚴(yán)格編譯選項(xiàng)后,如果使用了任何特定于編譯器的特性,那么編譯器將會(huì)給出相應(yīng)的警告/錯(cuò)誤。

        2 處理器架構(gòu)

        2.1 字節(jié)序

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

        圖1 字節(jié)序

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

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

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

        2.2 數(shù)據(jù)對齊

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

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

        C標(biāo)準(zhǔn)在stddef.h中定義了offsetof宏,用來返回結(jié)構(gòu)體成員的偏移值。為了查看成員y的偏移值可以使用下面的語句:

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

        結(jié) 語

        總之,在實(shí)踐中應(yīng)該編寫符合標(biāo)準(zhǔn)的代碼,隔離與特定處理器或者操作系統(tǒng)相關(guān)的代碼,甚至嘗試使用不同的編譯器編譯你的代碼,只有這樣才能確保代碼的可移植性。

        [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.程序設(shè)計(jì)實(shí)踐[M].裘宗燕 ,譯 .北京 :機(jī)械工業(yè)出版社,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.

        猜你喜歡
        小端編譯器字節(jié)
        No.8 字節(jié)跳動(dòng)將推出獨(dú)立出口電商APP
        基于相異編譯器的安全計(jì)算機(jī)平臺交叉編譯環(huán)境設(shè)計(jì)
        小端接觸同步器后備量分析與驗(yàn)證
        汽車零部件(2019年7期)2019-08-14 10:56:14
        No.10 “字節(jié)跳動(dòng)手機(jī)”要來了?
        簡談MC7字節(jié)碼
        唯一的守軍
        幸福(2016年5期)2016-04-19 03:48:10
        唯一的守軍
        視野(2015年21期)2015-02-05 05:32:34
        舊鍛模的再利用
        通用NC代碼編譯器的設(shè)計(jì)與實(shí)現(xiàn)
        編譯器無關(guān)性編碼在微控制器中的優(yōu)勢
        亚洲精品v欧洲精品v日韩精品| 精品国产又大又黄又粗av | 丰满多毛的大隂户视频| 国产高清吃奶成免费视频网站 | 色老头在线一区二区三区| 亚洲AV无码永久在线观看| 国产熟女乱综合一区二区三区| 日本一级片一区二区三区| 2021亚洲国产精品无码| 久久人人爽人人爽人人片av东京热| 国产日产高清欧美一区| 欧美综合自拍亚洲综合百度| 日本大片一区二区三区| 精品欧美一区二区三区久久久| 97久久草草超级碰碰碰| 色妺妺视频网| 在线播放中文字幕一区二区三区| 久久亚洲春色中文字幕久久| 日韩网红少妇无码视频香港| 军人粗大的内捧猛烈进出视频| 色综合久久久久综合999| 少妇人妻字幕一区二区| 国内自拍速发福利免费在线观看| 午夜射精日本三级| 国产亚洲视频在线观看网址| 国产精品玖玖资源站大全| 免费人妖一区二区三区| 亚洲一区二区三区尿失禁| 50岁熟妇的呻吟声对白| 久久国产免费观看精品| 最全精品自拍视频在线| 国产精品一区二区性色| 男女上下猛烈啪啪免费看| 中文字幕在线观看国产双飞高清 | 91精品人妻一区二区三区水蜜桃| 十四以下岁毛片带血a级| 久久不见久久见免费影院www| 一本一本久久a久久精品综合| 最新国产精品国产三级国产av| 少妇被猛烈进入到喷白浆| 亚洲第一av导航av尤物|