程式碼中 char* p = (char*)(st[2].errstr + 32); printf("%d", p - (char*)st); 輸出 120,核心在於指標減法結果以指標指向型別大小為單位,此處皆為 char*,故結果為位元組數差值。
struct st_t {
int status; // 4 bytes
short* pdata; // 4/8 bytes (假設 32 位元 4 bytes)
char errstr[32]; // 32 bytes
}; // 總計 40 bytes (含對齊)
st_t st[16]; // 連續 16 個結構體
(char*)st:陣列起始位址(第 0 個結構體開頭)。st[2].errstr:第 2 個結構體(索引 2,即第 3 個)的 errstr 成員起始位址。st[2].errstr + 32:errstr 陣列結束後的位址,即第 3 個結構體結束、第 4 個結構體開頭。p - (char*)st:兩 char* 相減,單位為 sizeof(char) = 1 byte,結果 = 120。ptr1 - ptr2 結果型別為 ptrdiff_t,值為「相差多少個 sizeof(*ptr) 單位」。sizeof(st_t) 可能大於成員大小總和。此例假設無額外填充(40 bytes)。st[2] 為第 3 個元素,偏移 2 * sizeof(st_t)。printf("sizeof(st_t)=%zu\n", sizeof(st_t)); // 40
printf("offsetof(errstr)=%zu\n", offsetof(st_t, errstr)); // 8
printf("st[2].errstr - (char*)st = %td\n", (char*)&st[2].errstr - (char*)st); // 88
printf("p - (char*)st = %td\n", p - (char*)st); // 120
掌握指標運算單位與結構體記憶體佈局,是 C 語言底層開發與逆向分析的基本功。