補充以前寫的:
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,看情況使用
結論,資料傳遞,要注意的眉角很多,不同資料結構,發送端和接收端都要想清楚,不能有錯!