這兩道題目是考察 C 語言底層功力的經典:一是運行時判斷 CPU 字節序 (Endianness),二是實作高效的字節序轉換 (Byte Swap)。看似簡單,卻能揭示候選人對記憶體模型、位運算、巨集/函式設計的掌握程度。
原理:將一個 16 位整數 0x1234 存入記憶體,讀取第一個位元組:
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint16_t val = 0x1234;
uint8_t *p = (uint8_t *)&val;
if (*p == 0x34) puts("Little Endian");
else if (*p == 0x12) puts("Big Endian");
else puts("Unknown");
return 0;
}
需求:0x1234 ↔ 0x3412,0x12345678 ↔ 0x78563412。
考點:位運算正確性、型別安全、巨集參數副作用、擴展性。
#include <stdint.h>
uint16_t bswap16(uint16_t x) {
return (x << 8) | (x >> 8);
}
uint32_t bswap32(uint32_t x) {
return (x << 24) | ((x << 8) & 0x00FF0000) |
((x >> 8) & 0x0000FF00) | (x >> 24);
}
#define BSWAP_16(x) \
((uint16_t)((( (uint16_t)(x) & 0x00FF) << 8) | \
(((uint16_t)(x) & 0xFF00) >> 8)))
#define BSWAP_32(x) \
((uint32_t)((( (uint32_t)(x) & 0xFF000000) >> 24) | \
(((uint32_t)(x) & 0x00FF0000) >> 8) | \
(((uint32_t)(x) & 0x0000FF00) << 8) | \
(((uint32_t)(x) & 0x000000FF) << 24)))
巨集關鍵防護:
(x) 防運算優先級錯誤。(uint16_t)(x) 截斷超寬輸入 (如 0x123490 → 0x3412)。(...) 包裹,確保單一表達式語意。do { ... } while(0) 若需多語句 (此處單表達式足夠)。int main(void) {
printf("BSWAP_16(0x1234) = 0x%X\n", BSWAP_16(0x1234)); // 0x3412
printf("BSWAP_16(0x123490) = 0x%X\n", BSWAP_16(0x123490)); // 0x9034 (截斷)
printf("bswap32(0x12345678) = 0x%X\n", bswap32(0x12345678)); // 0x78563412
return 0;
}
<arpa/inet.h> 的 htons/ntohs/htonl/ntohl (網路編程) 或 <byteswap.h> (GNU 擴展)。__builtin_bswap16/32/64,會優化為單條指令 (x86 bswap),效能最佳。