如何對於多位元組變數進行逐字節讀寫

2021-10-04 14:44:00 字數 4093 閱讀 5588

大部分程式語言都沒有直接給我們提供對於位進行操作的方法,有時候為了節約空間或者是實現一些特殊目的,我們需要對於乙個儲存空間中的某一段 「位串」 進行讀寫。

目錄

向指定位元組寫入資料

當被寫入的空間的二進位制位全是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 第一次呼叫,計算所...