前往
大廳
主題

雞同鴨講2,記憶體對齊(pragma pack)與位元順序(Endianness)

Yang | 2023-11-18 14:23:59 | 巴幣 0 | 人氣 113

補充以前寫的:
C程式碼排版與記憶體對齊
C語言的sizeof(long)和下一個千禧蟲問題

printf("%ld/%ld/%ld\n", sizeof(timeval), sizeof(timeval::tv_sec), sizeof(timeval::tv_usec));

測試在Windows (Win10 x64)上輸出8/4/4,
在Linux (CentOS7 x64)上輸出16/8/8,
在Unix (AIX7 x64)上輸出16/8/4!

沒找到Unix上記憶體對齊的設定在哪或如何調整,但自行寫程式觀察,
發現pragma pack要設為8,才會輸出16/8/4的結果,程式碼如下:

#pragma pack(8)

struct MyTimeval
{
    long tv_sec;
    int tv_usec;
};

printf("%ld/%ld/%ld\n", sizeof(MyTimeval), sizeof(MyTimeval::tv_sec), sizeof(MyTimeval::tv_usec));

#pragma pack()

//pack(1)或2或4,會輸出12/8/4

因為不同平台timeval(時間資料結構)內部欄位長度不太一樣,需要跨平台通訊時,要再多設計一層轉換步驟,

並且還要考慮平台是大端序(big-endian)或小端序(little-endian),參考資料:

const int value = 0x12345678;
const char *vPtr = (char *)&value;

printf("0x%08X\n", value);
printf("0x%02hhX %02hhX %02hhX %02hhX\n", vPtr[0], vPtr[1], vPtr[2], vPtr[3]);

大端序(big-endian)會輸出
0x12345678
0x12 34 56 78

小端序(little-endian)會輸出
0x12345678
0x78 56 34 12

長度2 bytes的整數資料發送時,要先用htons轉換,接收時,再用ntohs,轉換成主機本地端的位元順序

長度4 bytes的整數資料發送時,要先用htonl轉換,接收時,再用ntohl,轉換成主機本地端的位元順序

C語言只有原生提供2 bytes和4 bytes的整數轉換,所以網路上能查到很多8 bytes(htonll & ntohll)的實作方式

但其實資料在網路上傳遞,字串型態比數值型態更常見 (可能是較容易除錯,浮點數的轉換較方便,較不用考慮記憶體對齊等原因)

數值轉換成字串,個人認為snprintf最方便萬能,整數浮點數都能轉,其他方法不再贅述
(sprintf/vsprintf/vsnprintf...,很類似,很容易誤用)

字串轉數字,常見有atoi、atol、atof,看情況使用

結論,資料傳遞,要注意的眉角很多,不同資料結構,發送端和接收端都要想清楚,不能有錯!
送禮物贊助創作者 !
0
留言

創作回應

更多創作