C語言操作單個的位有什么技巧嗎?
謝邀。
1 個字節(Byte)等于 8 個位(bit)似乎已經是程序員間的常識了,很少有人質疑這一點。但是作為C語言程序員,我們常常要在不同的硬件平臺上做底層開發,應該明白:1個字節等于8個位只是慣例而已,C語言標準并沒有定義這一點。
有些編譯器并不遵守這個慣例,例如,在 Texas 的 C55x DSP 的平臺上,1 個字節等于 16 個位。在這個平臺上,各種數據類型占用的位數有些奇怪:
以 long long 為例,在該平臺上 long long 之所以等于 40 bit,而不是我們常用的 64 bit,是因為它們的 ALU 是 40 bit 寬,因此編譯器規定 long long 為 40 bit 可以降低功耗和提升效率。
C語言操作位C語言沒有類似于 Java 的“垃圾回收”等高級編程語言特性,也不像 python 那樣無需顯示聲明類型就能使用變量,因此在很多人看來,C語言有些“低級”。但是C語言的這些“低級”也是 C語言的優點——使用C語言開發程序,程序員能夠準確知道究竟使用了多少資源,以及哪些資源還在內存里,哪些已經被釋放。換句話說,C語言程序具備資源的使用確定性。
因此,C語言特別適合用于一些資源比較匱乏的項目開發中。在這些項目中,以嵌入式項目為代表,一般都需要嚴格控制內存的使用——使用 1 個字節(Byte)就能存放的值,絕對不定義 2 個字節寬度的變量。甚至,一些“摳門”的C語言程序員會將 1 個字節掰成若干個位(bit)使用。
所以,在C語言程序開發中,常常需要操作某個變量特定的位(bit),這對于C語言來說當然沒有任何難度,各種移位操作就能夠方便的解決該類需求,例如:
上面第二行C語言代碼將 status 的第3個位(bit 2)設置為 1,第三行C語言代碼將 status 的第1個位(bit 0)設置為 0。可以看出,借助于位運算,C語言可以比較簡單的操作 status 的指定位。不過,C語言這種操作位的方法有時候看起來不夠直觀——至少沒有直接賦值那么直觀。
那C語言有沒有更加直觀的位操作方法呢?
上面的例子通過移位、以及或與非等操作實現對變量 status 的位操作,但是看起來卻不是那么直觀,那么C語言有沒有更加直觀的位操作方法呢?似乎可以借助C語言的聯合體(union)和位域(bit field)語法,間接的實現位操作,請看下面的C語言代碼:
此例中 status 和 bits 結構體共享一個字節的內存空間,結構體 bits 利用C言中的位域語法將一個字節的內存空間拆分成 8 個位,這種情況下,要讀寫 status 的位就非常簡單了,請看下面的C語言示例代碼:
編寫 main() 函數,測試通過位域操作 status 的位,相關C語言代碼如下,請看:
main() 函數一開始將 status 置為 0,然后將它的 bit1 和 bit3 設置為 1,也就相當于將 status 設置為 0x0a,編譯并執行這段C語言代碼,得到如下輸出:
一切與預期一致,這樣就實現了以“賦值”的形式,操作C語言中的位,而且看起來比“移位與或非操作”更加直觀,所以這樣的操作更好了?
自然要看情況,比如在開頭提到的幾種已經平臺上,上述C語言代碼就不再適用了,另外, 就算在 1 個字節等于 8 個位的硬件平臺上,單個字節的 8 個位是如何分布的也是沒有明確標準的。這就導致上面這種基于位域的操作位的方法不具備可移植性。
不過,這種方法又的確可以帶來一些方便,具體取舍由題主決定了。
歡迎在評論區一起討論,質疑。文章都是手打原創,每天最淺顯的介紹C語言、linux等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。