大部分程式語言都沒有直接給我們提供對於位進行操作的方法,有時候為了節約空間或者是實現一些特殊目的,我們需要對於乙個儲存空間中的某一段 「位串」 進行讀寫。
目錄
向指定位元組寫入資料
當被寫入的空間的二進位制位全是0的時候
當被寫入的空間的二進位制位不是全是0的時候
從指定位元組讀取資料
封裝好的讀寫指定位元組的python函式
位操作原理總結 規律
寫入資料的2種方法
使用 位或 向目標空間的第n位開始寫入資料串
使用 位與 向目標空間的第n位開始寫入資料串
讀取資料的2種方法
使用 位與 來讀取目標空間的第n位開始長度為l的資料串
使用 位或 來讀取目標空間的第n位開始長度為l的資料串
我們要實現:對於第n位元組進行寫入資料和讀取資料,同時其他3位元組的資料不能受影響。
讓我們利用python來做這個實驗,為方便表示,我們利用十六進製制的表示方法來演示。
1個十六進製制位相當於4個二進位制位,所以1個位元組的8位在十六進製制的表示方法裡佔2個十六進製制位,比如 二進位制數 11110001 等於十六進製制數 f1。
在python中十六進製制資料 f1 用 0xf1 表示。
注意,被寫入的那一位元組空間在寫入前必須是全0!
例如:我們有乙個int型別的4位元組資料
a = 0xab120056讓我們從二進位制的角度來考慮,它的第二位元組為全為0,我們要向它的第二位元組寫入資料 0x34
關鍵一步來了,我們要構造另乙個int型別資料,其第二位元組的資料是我們想要寫入的資料 0x34,其他3位元組都是0
我們把這個構造的新int資料叫做掩碼
即
mask = 0x00003400我們也可以用位的位移操作符 << 來構造這個掩碼,只需要將資料位左移指定位元組就好,比如我們要移動到第二位元組就左移8位,第三位元組就左移16位。
mask = 0x34 << 8獲得了包含有我們要寫入的資料的掩碼後,我們就可以進行寫入操作了
我們只需要將被寫入的資料和掩碼做位或,將得到的值寫回被寫入的空間就行了
即
a = a|mask至此,資料 0x34 已經被寫入了int變數a所在的空間的第二位元組,並且其他資料沒有受到影響
print("a=「,a) # a=0xab123456如果被寫入的那一位元組在寫入前不為全零,我們是不能按上邊的方法直接構造掩碼並寫入的,我們要先將原來的非全零資料進行擦除,即先設法將其全置為零。
讓我們對於資料a = 0xab123456的第三位元組進行擦除
同樣,我們再構造乙個和被運算元據等長的掩碼,將掩碼的要擦除的位元組位置全置為0,不希望擦出的位元組位置全置為1。
我們要擦除第三位元組,就將掩碼的第三位元組的二進位制位全置為0,其餘部分全置為1
mask = 0xff00ffff讓我們對於目標的第三位元組進行擦除,只需用掩碼與被操作的資料進行位與操作,將得到的值覆蓋掉原來的值就好
a = a&mask至此,第三位元組的資料已經被擦除,即全置為0,並且其他資料沒有受到影響
print("a=「,a) # a=0xab003456擦除後,我們就可以像上邊那樣對於這一位元組進行寫入了,不再贅述。
我們已經成功地對於指定位元組寫入了資料,當我們想使用這些資料的時候,需要把它們讀取出來。
假如我們有資料a=0xab123456
我們想讀取其第二位元組的資料0x34
我們只需要構造乙個這樣的掩碼,其第二位元組二進位制位全為1,其餘位全為0
即
mask = 0x0000ff00我們要讀取目標資料的第二位元組,只需要使用掩碼與目標資料進行位與,再將得到的結果進行右位移,將想要的資料位移到最低位即可
即
a = a&maskprint("a=「,a) # a=0x00003400a = a >> 8print("a=「,a) # a=0x00000034至此,我們就成功的從指定資料的第二位元組讀取了資料。
def writebyte(var_to, data, which_byte):
# 構造含有資料的寫入掩碼
mask_data = data << (which_byte-1)*8
# 構造擦除指定位元組的擦除掩碼
mask_tozero = ~(0xff << (which_byte-1)*8)
# 不管要寫入的位原來是什麼情況,一律先擦除
var_to = var_to & mask_tozero
# 寫入資料
var_to = var_to | mask_data
return var_to
def readbyte(var_from, which_byte):
# 構造可以讀取指定位元組的讀取掩碼
mask_read = 0xff << (which_byte-1)*8
# 讀取資料
data = var_from & mask_read
# 提取資料
data = data >> (which_byte-1)*8
return data
# 原始資料
a = 0xab123456
# 寫入在第二位元組寫入資料 0xcd
a = writebyte(a, 0xcd, 2)
# 列印一下
print(hex(a)) # 0xab12cd56
# 讀取第二位元組的資料
data = readbyte(a, 2)
# 列印一下
print(hex(data)) # 0xcd
位操作真是一件很神奇的事情,明明就是一些簡單的規則(與/或)
如果從另乙個角度來看待這些操作,就會有新用法
將以上特性推廣到二進位制串
掩碼的構造:構造乙個和被寫入空間等長的全0串,從第n位開始,將要寫入的資料放入這個全0串
目標空間:要事先將被寫入的位置串全部置0
操作:目標空間資料 位或 掩碼
得到的結果再寫入目標空間
掩碼的構造:構造乙個和被寫入空間等長的全1串,從第n位開始,將要寫入的資料放入這個全0串
目標空間:要事先將被寫入的位置串全部置1
操作:目標空間資料 位與 掩碼
得到的結果再寫入目標空間
掩碼的構造:構造乙個和被寫入空間等長的全0串,從第n位開始到後邊的l為都置1
操作:目標空間資料 位與 掩碼
得到的資料再 右位移 ,將資料段位移到最低位,得到想讀取的資料。
掩碼1的構造:構造乙個和被寫入空間等長的全1串,從第n位開始到後邊的l為都置0
掩碼2的構造:構造乙個和被寫入空間等長的全0串,從第n位開始到後邊的l為都置1
操作:目標空間資料 位或 掩碼1
將上一步得到的結果 同 掩碼2 進行 位與
得到的資料再 右位移 ,將資料段位移到最低位,得到想讀取的資料。
寬位元組 多位元組 mbstowcs wcstombs
函式 size t wcstombs char dest,const wchar t src,size t n wide character to a multibyten 被寫入到 str 中的最大位元組數 size t mbstowcs wchar t dest,const char src,s...
寬位元組 多位元組 單位元組 的問題
感覺比較混亂,學習了一通,做個記錄。著急在windows下面用的話,可以先看這個 vc windows 平台字元透明程式設計大總結 寬字串與單位元組字串之間的轉換。c 標準裡面已經提供了 寬位元組轉單位元組 size twcstombs char mbstr constwchar t wcstr s...
多位元組與寬位元組之間的轉換
1 函式 widechartomultibyte 轉換 unicode 到 mbcs。lpcolestr lpw l hello,你好 size t wlen wcslen lpw 1 寬字元字元長度,1表示包含字串結束符 int alen widechartomultibyte 第一次呼叫,計算所...