x86 架構普遍採用小端模式,而 PowerPC 等處理器可配置為大端或小端。代碼在舊板卡(小端)運行完美,換到新板卡(大端)卻莫名其妙報錯,且極難調試——因為開發者往往根本不會懷疑是字節序問題。
void i2c_write(..., unsigned char *reg, ...); // reg 為寄存器地址指針
// 調用處
int cTest = 2;
i2c_write(..., (unsigned char *)&cTest, ...);
int cTest = 2,內存佈局(低地址→高地址):02 00 00 00。
(unsigned char *)&cTest 取得的是最低地址,即 0x02 所在位置,傳遞正確。
同樣 cTest = 2,內存佈局:00 00 00 02。
(unsigned char *)&cTest 仍取最低地址,但此時該位置存儲的是 0x00(最高有效位),導致寄存器地址錯誤,通信失敗。
(unsigned char *)&cTest 必須指向該對象佔用內存區域的起始地址(最低地址),與大小端無關。int 的低位字節一定在起始地址,這只在小端成立。大端下起始地址存的是高位字節。unsigned char *(單字節地址),卻強行轉換 int *,違反嚴格別名規則,行為未定義。unsigned char,就聲明 unsigned char reg = 0x02; 並傳 ®。char 是否帶符號,顯式使用 signed char 或 unsigned char。htonl/ntohl 或手動移位),不可依賴宿主字節序。__attribute__((packed, aligned)) 控制結構體佈局,但不能改變基本類型的字節序。這個「小問題」耗時數天排查,根源在於隨意的類型轉換與隱含的大小端假設。嚴格的類型系統思維、顯式的字節序處理、拒絕「碰巧能跑」的代碼,是跨平台 C 編程的生存法則。