當心!別又踩了大小端的坑

2021-10-25 08:50:35 字數 2326 閱讀 6778

程式執行在記憶體中,計算機中的最小儲存單位是bit,即10的二進位制,它可以識別的機器碼就是以二進位制形式儲存的;

記憶體由多個儲存單元組成,每個儲存單元都有乙個唯一的數字位址位元組可定址記憶體。每個儲存位置可以包含固定數量的二進位制數字。

在大多數的現代計算機上,位址的最小資料的長度為8位,稱為位元組(1 byte = 8 bit);

一般計算機中使用者程式直接訪問的位址是虛擬記憶體的位址,作業系統核心會根據使用者程式訪問的虛擬位址,找出頁表中對於的實體地址,最終定址到所需要的資料;具體如下圖所示;

然而,在mcu等裸機開發的環境中,沒有mmu,則程式直接訪問的是物理記憶體,所以無論是計算機還是mcu在程式執行中都需要記憶體作為載體,儲存資料和執行程式。那麼,下面再來看是程式以及資料在記憶體中是以何種形式儲存的?

前面提到過,在大多數的現代計算機上,位址的最小資料的長度為8位,稱為位元組(1 byte = 8 bit);至於為什麼是8位?看起來似乎有點玄學,並且很吉利的乙個數字,但是老外好像沒有數字迷信,這裡的原因大概是因為這幾點;

在說大小端之前,要先提一下位元組順序(endianness),它是描述資料以位元組為一組在計算機記憶體中儲存順序的術語。

位元組順序可以是大端順序(big-endian)或者小端順序(little-endian);在對多位元組資料進行儲存時,一般遵循以下規則;

資料0x01020304分別在大端機器和小端機器中的儲存形式,具體如下圖所示;

在大多數情況下,編譯器會處理位元組順序,從而避免出現大小端不一致的問題,但是在以下情況下位元組順序就會成為乙個問題。

在通訊中,例如網路程式設計:假設在小端機器上向檔案寫入整數,然後將此檔案傳輸到大端機器上。如果沒有做大小端轉換,那麼大端機器就會以相反的順序讀取檔案

tcp/ip協議中,預設使用的是大端順序,它與具體的cpu型別、作業系統等無關;

那麼如何在程式中快速的區分大小端呢?

下面介紹幾種通過c語言實現大小端判斷的方法;

第一種通過指標的記憶體對齊來實現;

函式的形式;

unsigned

char

check_endian

(void

)

巨集定義的形式;

static uint32_t endianness =

0xdeadbeef

;enum endianness

;#define endianness ( *(const char *)&endianness == 0xef ? little \

: *(const char *)&endianness == 0xde ? big \

: assert(0))

更加簡潔;

#define is_big_endian (!*(unsigned char *)&(uint16_t))
第二種通過結構體和聯合體的記憶體對齊來實現;

#ifndef order32_h

#define order32_h

#include

#include

#if char_bit != 8

#error "unsupported char size"

#endif

enum

;static

const

union

o32_host_order =};

#define o32_host_order (o32_host_order.value)

#endif

當然具體的方法還有很多,本文就先講到這裡。

那些移動端web踩過的坑

扔了n久,還是撿回來了。好好弄一下吧。剛工作的時候挺忙的,後來不那麼忙了,但是變懶了。這一年大多數時間都在在做移動端的東東,做了之後才發現,同樣是web前端,移動端的坑真的是深不可測,各種各樣的,只有想不到,沒有遇不到。在這裡把最近踩過的坑整理一下。首先,要解決的關鍵問題是如何為裝置選擇可視視口尺寸...

踩坑 Integer型別的整數比較大小

先劃重點 integer型別的整數比較數值大小用equals.和intvalue 盡量別用 去比較是否相等 之前沒注意過integer型別比較數值大小,一直在用 某天,寫的一段程式沒跑通,才注意到這個問題 public static void main string args 結果 true tru...

踩了apache配置虛擬主機的坑

一直使用xampp做apache伺服器,可是新版的xampp新增了虛擬主機就訪問127.0.0.1也跳轉到了虛擬主機去了,比如 我新增了www.demo.com,路徑是e www demo,而我的新增完之後,訪問127.0.0.1竟然也是跑到了www.demo.com下面去。上網找了好多數據說是新增...