不同於陣列,結構體變量之間可直接賦值:
struct Foo { char a; int b; double c; } foo1, foo2;
foo2 = foo1; // 合法,執行記憶體逐位拷貝
編譯器將結構體視為一塊連續記憶體,按字長(如 4 位元組)分塊複製。對齊導致 sizeof(Foo)=16,產生四條 movl 指令,而非逐欄位複製。
struct Foo { int n; double d[2]; char *p_c; } foo1, foo2;
char *c = malloc(4); strcpy(c, "abc");
foo1 = (Foo){1, {2,3}, c};
foo2 = foo1; // p_c 同指向同一塊堆記憶體
後果:釋放 foo1.p_c 後,foo2.p_c 成懸空指針。C++ 可透過重載 operator= 實現深拷貝,C 需手寫拷貝函數。
| 特性 | 結構體(一等公民) | 陣列(二等公民) |
|---|---|---|
| 可作函數參數 | 是(傳值或傳址) | 退化為指針,失去大小資訊 |
| 可作函數返回值 | 是 | 否 |
| 可直接賦值 | 是 | 否(a=b 編譯錯誤) |
| 可運行時構造 | 是 | 僅靜態/編譯期 |
早期 C 為簡化編譯器,將陣列設計為「指向首元素的指針常量」。將陣列包裝進結構體即可獲得一等公民待遇:
struct Wrapper { int arr[10]; };
Wrapper w1, w2; w2 = w1; // 合法,包含陣列內容完整拷貝