首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言結構體數組:&G[i] 與 &G[i].data 地址相同的原理

     編輯:程式設計綜合問答

問題現象

結構體定義:

struct VNode {
    int data;
    ArcNode *firstarc;
};
struct VNode G[MAX_SIZE];

代碼中 scanf("%d", &G[i]); 直接對結構體數組元素取地址賦值,但結構體包含兩個成員,為何能正確賦值給 data?

核心原理

結構體變量的地址 = 其第一個成員的地址。

  • C 標準保證:結構體對象的起始地址與其第一個成員的地址完全相同
  • &G[i] 的類型是 struct VNode*,值為結構體起始地址
  • &G[i].data 的類型是 int*,值同樣為結構體起始地址
  • 兩者數值相等,類型不同

內存佈局圖解

G[i] 內存佈局:
+----------------+------------------+
|   data (int)   | firstarc (ptr)   |  <- 連續內存
+----------------+------------------+
^
|___ &G[i] == &G[i].data (同一地址)

scanf 行為解析

scanf("%d", &G[i]);
  • %d 期望 int* 參數
  • 傳入 struct VNode*,編譯器發出類型不匹配警告(但允許編譯)
  • 運行時:scanf 將讀取的整數寫入該地址起始的 sizeof(int) 字節
  • 恰好覆蓋 data 成員區域 → 達到「給 data 賦值」的效果

標準寫法與最佳實踐

// 明確指定成員,類型安全,可讀性強
scanf("%d", &G[i].data);

// 或使用指針中間變量
struct VNode *p = &G[i];
scanf("%d", &p->data);

編譯器差異說明

  • GCC/Clang:默認報警告 format '%d' expects argument of type 'int*', but argument has type 'struct VNode*'
  • MSVC (VS):較寬容,可能僅給警告甚至不警告
  • C 標準:行為屬於未定義行為(類型不匹配的指釖傳遞),雖然在主流平台上「剛好能跑」

總結

&G[i] 能給 data 賦值,利用的是結構體首地址等於首成員地址的內存佈局特性,屬於非標準、不安全的「巧合」用法。生產代碼必須使用 &G[i].data 明確指定成員。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved