很多C語言程式設計師都知道「大小端」,但並不知道何時才應該考慮它

2021-01-13 IT劉小虎

上一節討論了C語言的 union 語法的一個使用場景,讀者應該發現,union 成員共享一塊內存的特性使得C語言程式設計師能夠寫出更加節約資源的程序。不過也有讀者在看了上一節文章後,評論或者私信說了一些關於C語言 union 的特性,這些回復有些是不嚴謹的。

如果不能完全掌握 union 語法,在使用時難免會覺得困惑,甚至跳入「陷阱」,寫出有隱患的C語言代碼。我稍稍總結了一下讀者回覆中關於 union 語法的誤解,主要可以分為兩大類。

誤區1:union 成員必須等長度

下面這段C語言代碼節選自上一節:

這段C語言代碼節選自上一節

有讀者評論稱:「要是union不同成員的大小不一樣就不能這麼用了」。他認為C語言的 union 成員必須是等長的,否則就不可使用。這麼認為也有一定的理由:union 成員共用一塊內存,如果成員不等長,那差異長度怎麼算呢?

差異長度怎麼算呢?

那麼,C語言中的 union 成員到底是不是必須長度相等呢?下面是一個例子,請看:

C語言中的 union 成員

顯然,成員 c 和 i 長度並不相等,那是否這麼定義 u 就不對了呢?我們編寫相應的C語言代碼測試之:

測試C語言代碼

編譯這段C語言代碼並執行,得到如下輸出:

輸出

可見編譯器並沒有報錯。雖然我們僅使用了 union 的成員 c(佔用1位元組),但是 test 仍然佔用了 4 個字節。顯然,即使 union 的成員不等長,使用起來也完全沒有問題,而且 union 佔用內存的空間等於最長的那個成員佔用的內存空間。

誤區2:使用 union 必須考慮大小端問題

有讀者(@Fishmoo)回覆說:「共用體(union)要在確定硬體大小端的情況下使用」。這個觀點對不對呢?在回答這個問題之前,首先需要了解「大小端」的概念。

簡單來說,「大小端」是指數據在內存中的字節順序。例如 int 型變量 a=0x12345678 佔用 4 個字節,在大端字節序的機器上,int 數據的高位位於低地址。在小端字節序的機器上,int 數據的高位位於高地址。

「大小端」

關於「大小端」這個名稱,有一段比較有趣的故事:

Lilliput和Blefuscu這兩個強國在過去的36個月中一直在苦戰。戰爭的原因:大家都知道,吃雞蛋的時候,原始的方法是打破雞蛋較大的一端,可以那時的皇帝的祖父由於小時侯吃雞蛋,按這種方法把手指弄破了,因此他的父親,就下令,命令所有的子民吃雞蛋的時候,必須先打破雞蛋較小的一端,違令者重罰。然後老百姓對此法令極為反感,期間發生了多次叛亂,其中一個皇帝因此送命,另一個丟了王位,產生叛亂的原因就是另一個國家Blefuscu的國王大臣煽動起來的,叛亂平息後,就逃到這個帝國避難。據估計,先後幾次有11000餘人情願死也不肯去打破雞蛋較小的端吃雞蛋。這個其實諷刺當時英國和法國之間持續的衝突。Danny Cohen一位網絡協議的開創者,第一次使用這兩個術語指代字節順序,後來就被大家廣泛接受。

那麼,大小端和 union 有什麼關係呢?讀者應該明白,C語言中 union 語法最重要的性質就是成員共享一塊內存區域,我們改寫上面的C語言代碼:

改寫上面的C語言代碼

因為在我的機器上,成員 i 佔用 4 個字節內存空間,所以將成員 c 改為數組 char c[4]。現在編寫下面這段C語言代碼:

C語言代碼

這段C語言代碼會輸出什麼呢?因為成員 c 和 成員 i 共享同一塊內存,所以 c 在內存中的起始地址和 i 的一致,i 是一個 4 字節變量,它的值在內存中分布因機器「大端」和「小端」而異。編譯這段C語言代碼並執行,得到如下輸出:

# gcc t.c# ./a.out0x780x560x340x12

可見,高位在低地址,此時C語言程序運行在「大端」機器上。讀者可自行測試上面這段C語言代碼,應該會發現,如果自己的機器是「小端」架構,則C語言程序最終的輸出會與這裡有一定的差異。

現在知道「大小端」與C語言 union 的關係了。那是不是只要使用 union,就一定要考慮「大小端」問題呢?當然不是了,例如上一節中的 union 例子,就完全不需要考慮「大小端」問題。只有涉及到使用「小變量」解釋「大變量」內存區域時,才需要考慮「大小端」問題。

看了本專欄之前文章的讀者應該明白,C語言中的數據類型的一大作用就是告訴編譯器該如何解釋它所在內存裡存放的數據的。例如一個 4 字節內存區域:

4 字節內存區域

編譯器要將這塊內存裡的數據取出使用,先要知道該怎麼取——它這塊內存可以表示 4 個 char 型變量,也可以表示 2 個 short 型變量,還可以表示 1 個 int 型變量。如果告訴編譯器這段內存表示一個 int 型數據,編譯器會自動按照當前機器的「大小端」解釋這個數據,就無需程式設計師再多操心了。如果告訴編譯這段內存表示 4 個 char 型變量(小變量),則編譯器會按照地址順序解釋這段內存,輸出就與「大小端」有關了。

小結

本節簡要介紹了C語言 union 語法的性質,較為詳細的討論了上一節讀者關於 union 的兩個誤區。現在應該明白,C語言的 union 成員不一定是等長的,使用 union 並不總是需要考慮「大小端」問題。事實上,「大小端」問題不是 union 語法的專屬考慮,在C語言程序開發中,很多情況都需要考慮這個問題,以後有機會再說了。

點個讚再走吧

歡迎在評論區一起討論,質疑。文章都是手打原創,每天最淺顯的介紹C語言、linux等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。

相關焦點

  • c語言之共用體union、枚舉、大小端模式
    枚舉在C語言中其實是一些符號常量集。直白點說:枚舉定義了一些符號,這些符號的本質就是int類型的常量,每個符號和一個常量綁定。這個符號就表示一個自定義的一個識別碼,編譯器對枚舉的認知就是符號常量所綁定的那個int類型的數字。枚舉符號常量和其對應的常量數字相對來說,數字不重要,符號才重要。符號對應的數字只要彼此不相同即可,沒有別的要求。
  • 為什麼 C 語言是程式設計師的首選,你知道嗎?
    C 語言是第一選擇對於大部分程式設計師,C語言是學習編程的第一門語言,很少有不了解C語言的程式設計師。如果有一個系統是用Java開發的,那那個系統開發的首選語言,也一定是Java。不過很可惜,真正能夠用來開發作業系統的語言並不多,而Java、Python這些都是在C之上實現的。
  • C語言學習篇(24)——大小端模式初探
    引言:什麼是大小端模式在計算機通信過程中,經常會遇到一個問題,是先發送數據的高字節還是先發送低字節呢?比如我們經常可以在網絡通訊協議中,都能聽到」大端(big endian)模式」這一詞,與之對應的是&34;,發送方和接收方必須按照相同的字節順序來處理數據,否則就會出現錯誤。
  • 每個C語言程式設計師都應該明白,計算機究竟是如何存儲小數的?
    本文不可能將複雜的數值算法以及相關的C語言程序開發經驗一一列出。事實上,討論如何以理想的數值精度進行計算,就和討論如何編寫最快的C語言程序,如何設計一款優秀的軟體一樣,主要取決於程式設計師本身的綜合素質。鑑於此,這裡將嘗試介紹一些基礎的,我認為每個C語言程式設計師都應該知道的內容。相等首先,我們應該明白C語言程序開發中的兩個浮點數何時相等。
  • 自學C/C++,如何成為程式設計師大牛,這些必須要知道
    C/C++這個語言已經經過30多年的歷練了。c/c++是不可否認,它學習的難度要比其它的語言要高。而它的學習難度,主要來自於它的複雜性和連貫性。現在C++的使用範圍比以前已經少了很多,java、C#、python等語言在很多方面已經可以代替 C++。但是有很多的細節還是無法更改修正的,主要集中在需要運行效率比較高的行業,比如遊戲、高效的伺服器。
  • 新入行的程式設計師應該學習哪門程式語言?
    新入行的程式設計師最常詢問我的問題之一就是:我應該學習哪門程式語言。我曾指導過很多開發者,他們總是懷疑自己的選擇,甚至改變主意,不斷地從一門程式語言跳躍到另一門程式語言,總是擔心做出錯誤的決定。如果你總是糾結於「我到底應該學習哪門程式語言」,本章正好適合你。首先,我會消除一些疑問;然後,我將就如何選擇你的第一門程式語言給你一些實用的考慮因素。
  • 很多程式設計師都不知道,C語言中還有「快類型」和「小類型」
    C語言逐步增加了許多好用的功能stdint.h頭文件如果程式設計師希望寫出可移植的C語言程序,首先最重要的一點是不能假定位寬。為了解決這樣的問題,在新標準文件「stdint.h」 之前,程式設計師必須做些額外的工作,以確定C語言代碼運行的平臺的各種數據位寬,這樣的工作著實煩人,稍不留神就會出錯。「stdint.h」頭文件的添加就是為了便於程式設計師寫出不假定位寬的程序的。
  • C語言陷阱與技巧31節,都說void*指針是「萬能指針」,它萬能在哪
    沒有程式設計師願意憑空造輪子奇怪的 void* 指針事實上,C語言標準庫提供了非常豐富的成熟函數供程式設計師使用,不過不知道讀者注意到沒,有些庫函數的參數是 void * 類型的,例如:void *memcpy
  • 腦殘式網絡編程入門(九):面試必考,史上最通俗大小端字節序詳解
    程式設計師在寫應用層程序時,一般不需要考慮字節序問題,因為字節序跟作業系統和硬體環境有關,而我們編寫的程序要麼不需要跨平臺(比如只運行在windows),要麼需要跨平臺時會由Java這種跨平臺語言在虛擬機層屏蔽掉了。
  • 每一個Java開發的程式設計師都應該知道的Java發展史
    ·那麼當時呢這個開發工程師呢想用這個c 加加來編寫。那麼後來呢發現c 加加呢非常的複雜,而且呢安全性呢呃也比較差。那於是呢這個小組呢就另闢蹊徑啊,那麼打算開發一門新的語言。那麼希望這門語言呢可以是簡單的,非常可靠的,並且呢是易於移植的。那麼基於這兒呢,他們就開發了一門新的語言叫java 用來編寫的一個電子產品設備。
  • C語言學習篇(25)——測試大小端模式的「坑」
    引言上一篇我們介紹了如何使用共用體和指針方式測試機器的大小端模式,並實際測試了本機x86_64是小端模式,C51機器是大端模式。 結論是以上兩種方式是可靠有效的,除了這2種方法,大家開動下自己的小腦袋,思考是否還有其他方法測試呢? 那麼今天我們就來嘗試下其他幾種方法,並分析其是否可靠有效。
  • 為什麼C++比C要麻煩?程式設計師這樣說,終於知道他為什麼單身了
    聽過一個笑話,程式設計師們互相聊天,程式設計師A問到:為什麼C++比C麻煩那麼多?」程式設計師B回答道:「有了對象能不麻煩麼。」同樣衍生出來的還有一個小故事:情人節,有人看到C一個人喝酒,便問:你的好哥們C++、Java、Python他們呢?C說:都過情人節去了。
  • 你知道「C」語言對程式設計師有多重要嗎?
    而C語言就像是「優秀程式設計師」的構建塊。就像細胞對複雜組織的作用一樣。沒有它也許你也可以成為一個優秀的程式設計師,但是有了它,你就如同擁有了左右臂,會讓您在學習編程的路上輕鬆,快樂。好了,話不多說,我們了解下:1.內存管理:我們很多人可能都來自
  • 為什麼很多人選擇放棄學習C語言?
    筆者嘗試著分析可能有以下幾種原因C語言入門相對比較難以前的老程式設計師入門語言基本上都是C語言,因為程式語言的種類少,而且相對C++來說還是簡單太多,所以當仁不讓的最佳程式語言,而且早期的程式設計師還覺得java語言裡面沒有指針學習起來沒有深度,編程界曾經有一種鄙視鏈,做底層開發的看不上上層應用開發的,覺得太膚淺,做上層應用開發覺得做底層的思維太陳舊太死板。
  • 程式設計師都是用什麼畫圖工具繪製C語言流程圖?這個方法你需要知道
    對於編程初學者來說,很多人都以為程序設計就是單純的寫代碼,其實並不是,程序設計是給出解決特定問題程序的過程,是軟體構造活動中的重要組成部分,往往以某種程序語言為工具,給出這種語言下的程序,很多人在接到一個新任務時馬上就摸到鍵盤一直敲,結果敲著敲著都不知道自己在敲什麼,而那些聰明的人在新任務接手之前都將繪製出一張程序流程圖
  • 不同語言的程式設計師不要再相互鄙視了!
    當今只要提到程式設計師,基本上都是這三種主流語言,並且最有錢的還不是這三種主流語言,這說明什麼呢? 圖片來之網際網路語言的作用其實計算機語言的設計都是為了解決相應的問題的,他們之間各有各的特點和優勢,只有解決了現實問題才是關鍵,比如C++做桌面軟體的較多,而java,Objective-c做手機
  • 為什麼很多java程式設計師都不喜歡PHP程式設計師?
    為什麼很多java程式設計師都不喜歡PHP程式設計師?這不是引戰的標題,小編是根據身邊很多程式設計師講述,特別是比較喜歡java程式設計師而總結出來的。在工作中,很多公司隨著業務的增加與需求多樣性,有些企業就是要求用PHP開發,所以很多開發公司都是跟著市場走,主流的程式語言java與PHP碰面,多數情況下java程式設計師都不喜歡PHP程式設計師。PHP號稱世界上最好的程式語言,在java程式設計師覺得PHP能開發的,java同樣能開發,而且比PHP還好,所以不認為PHP是世界上最好的程式語言,java才是世界最好的程式語言。
  • C語言為什麼要有「->」運算符,為何不使用點運算符代替它呢?
    基本上,每一個C語言程式設計師都明白點運算符「.」和箭頭運算符「->」可以用於訪問結構體的成員,只不過箭頭運算符「->」需要與結構體指針結合使用。事實上按照現在流行的C語言語法,通過結構體指針直接訪問成員,也只能通過箭頭運算符。
  • 學習c語言,知道這三個資源就行了
    c語言作為目前最熱門的程式語言之一,一直是學生、程式設計師必須學習的課程之一,但目前許多學校的課程太過老舊,教材和教程也參差不齊,這裡就給大家推薦幾個比較好的學習c語言的資源。第一個推薦的就是《C Primer Plus》,作為一本廣受大家認可的工具書,書中詳細地講解了C語言的基本概念和編程技巧,並且包含了許多習題和例子,可以有效的幫助初學者建立對於C語言的知識體系,是一本對小白比較友好,且內容全面的入門教材。
  • 陝西計算機二級c語言培訓班
    陝西計算機二級c語言培訓班,市面上的培訓機構越來越多,甚至有些新成立的小機構大力宣傳,結果只有一兩個老師和幾個市場人員,遇到這樣的計算機培訓機構需要擦亮雙眼,這樣的培訓機構既保證不了學到的內容,也保證不了就業。