當大類型賦值給小類型(如 `int` → `char`),高位被截斷,保留低位。C 標準規定:無符號類型截斷保留低位(模 2ⁿ);有符號類型屬實現定義行為(普遍採用補碼截斷)。
#include <stdio.h>
int main(void) {
char sum;
int val = 4874; // 0x0000130A
sum = val; // 截斷保留低 8 位:0x0A (10)
printf("sum = %d (0x%02X)\n", sum, (unsigned char)sum);
// 輸出: sum = 10 (0x0A)
// 驗證位模式
printf("val hex: 0x%08X\n", val);
printf("低位字節: 0x%02X\n", val & 0xFF);
return 0;
}
結論:x86/ARM 等小端機器上,`int` 低地址存低位字節,`char` 取低地址字節 → 保留低 8 位。
| 模式 | 低地址存放 | 高地址存放 | 典型架構 |
|---|---|---|---|
| 小端 | 最低有效字節 (LSB) | 最高有效字節 (MSB) | x86, ARM, RISC-V |
| 大端 | 最高有效字節 (MSB) | 最低有效字節 (LSB) | PowerPC, SPARC, 網絡序 |
#include <stdio.h>
int is_little_endian(void) {
union {
uint32_t i;
uint8_t c[4];
} u = { .i = 0x01020304 };
return u.c[0] == 0x04; // 低地址存 04 → 小端
}
int main(void) {
printf("Little Endian: %s\n", is_little_endian() ? "Yes" : "No");
return 0;
}
int is_le(void) {
uint32_t x = 1;
return *(uint8_t *)&x; // 可能違反 strict aliasing,建議用 union
}
// GCC/Clang/MSVC
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
// 小端
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
// 大端
#elif defined(_WIN32) || defined(__x86_64__) || defined(__aarch64__)
// 常見小端平台
#else
// 運行時檢測
#endif
#include <arpa/inet.h> // htonl, ntohl, htons, ntohs
#include <stdint.h>
// 手寫版本(無標準庫時)
uint32_t htonl_manual(uint32_t host) {
// 假設宿主機為小端
return ((host & 0xFF) << 24) |
((host & 0xFF00) << 8) |
((host & 0xFF0000) >> 8) |
((host >> 24) & 0xFF);
}
uint16_t htons_manual(uint16_t host) {
return (host << 8) | (host >> 8);
}
int a = INT_MAX;
a += 1; // UB!編譯器可假設永不發生,優化掉檢查
// 安全檢查
if (a > 0 && b > INT_MAX - a) overflow();
else a += b;