typedef struct Data {
int arr[10];
int* p_low;
int* p_high;
} Data;
int main() {
Data* data = NULL;
printf("%p\n", data->arr); // 1. 未崩潰:arr 是柔性數組/固定數組,偏移量編譯期可知
printf("%p\n", &(data->arr[1])); // 2. 未崩潰:同理,偏移量計算不解引用
printf("%p\n", data->p_low); // 3. 崩潰:p_low 是指針成員,需解引用 data 讀取其值
return 0;
}
| 表達式 | 操作 | 是否解引用 data | 結果 |
|---|---|---|---|
data->arr | 取數組首地址(結構體起始偏移 0) | 否(編譯期常量偏移) | 輸出 0x0 |
&(data->arr[1]) | 取元素地址(偏移 sizeof(int)) | 否 | 輸出 0x4 |
data->p_low | 讀取指針成員值(偏移 40/48 字節) | 是(需讀取 0x0+offset 處內存) | Segmentation Fault |
-> 操作符隱含解引用:ptr->member 等價於 (*ptr).member。ptr == NULL,任何嘗試讀取/寫入成員內存的操作均導致未定義行為(通常 Crash)。// 正確:分配內存後再訪問
Data* data = malloc(sizeof(Data));
if (data) {
data->p_low = &data->arr[0];
data->p_high = &data->arr[9];
// 使用...
free(data);
}
// 或棢查非空
if (data != NULL) {
printf("%p\n", data->p_low);
}
-fsanitize=address -g (GCC/Clang),運行時精確報告空指針解引用位置。run → 崩潰後 bt 回溯,frame N 查看局部變量。cppcheck --enable=all、Clang Static Analyzer、Coverity 可編譯期發現。「指針用前必判空」是 C/C++ 開發者的肌肉記憶,任何結構體指針解引用前務必確認非空。