成員存取運算子
成員存取運算子允許存取其運算元的成員。
| 運算子 | 運算子名稱 | 範例 | 描述 |
|---|---|---|---|
| [] | 陣列下標 | a[b] | 存取陣列 a 的第 b 個元素 |
| * | 指標取值 (dereference) | *a | 對指標 a 取值,以存取其所指涉的物件或函式 |
| & | 取址 | &a | 建立一個指涉物件或函式 a 的指標 |
| . | 成員存取 | a.b | 存取 struct 或 union a 的成員 b |
| -> | 透過指標存取成員 | a->b | 存取由 a 所指之 struct 或 union 的成員 b |
目錄 |
[編輯] 下標
陣列下標表達式的形式為
指標表達式 [ 整數表達式 ] |
(1) | ||||||||
整數表達式 [ 指標表達式 ] |
(2) | ||||||||
其中
| 指標表達式 | - | 指向完整物件的指標型別之 表達式 |
| 整數表達式 | - | 整數型別的 表達式 |
下標運算子表達式是一個 左值表達式,其型別為 指標表達式 所指向物件的型別。
根據定義,下標運算子 E1[E2] 與 *((E1)+(E2)) 完全相同。若 指標表達式 為陣列表達式,它會經歷 左值至右值轉換 並成為指向陣列第一個元素的指標。
由於 指標與整數相加 的定義,結果為陣列中索引等於 整數表達式 結果的元素(或者,若 指標表達式 原本指向某陣列的第 i 個元素,則結果的索引為 i 加上 整數表達式 的結果)。
注意:關於多維陣列的詳細資訊,請參見 陣列。
#include <stdio.h> int main(void) { int a[3] = {1,2,3}; printf("%d %d\n", a[2], // n == 3 2[a]); // same, n == 3 a[2] = 7; // subscripts are lvalues int n[2][3] = {{1,2,3},{4,5,6}}; int (*p)[3] = &n[1]; // elements of n are arrays printf("%d %d %d\n", (*p)[0], p[0][1], p[0][2]); // access n[1][] via p int x = n[1][2]; // applying [] again to the array n[1] printf("%d\n", x); printf("%c %c\n", "abc"[2], 2["abc"]); // string literals are arrays too }
輸出
3 3 4 5 6 6 c c
[編輯] 取值
取值 (dereference) 或 間接 (indirection) 表達式的形式為
* 指標表達式 |
|||||||||
其中
| 指標表達式 | - | 任意指標型別的 表達式 |
若 指標表達式 是指向函式的指標,則取值運算子的結果為該函式的函式指示項 (function designator)。
若 指標表達式 是指向物件的指標,則結果為一個指涉該物件的 左值表達式。
對空指標、生命週期結束的物件指標(懸空指標)、未對齊的指標或具有不確定值的指標進行取值,屬於未定義行為;除非當取值運算子的結果被套用取址運算子抵銷時,例如 &*E。
輸出
*p = 1 *p = 7
[編輯] 取址
取址表達式的形式為
& 函式 |
(1) | ||||||||
& 左值表達式 |
(2) | ||||||||
& * 表達式 |
(3) | ||||||||
& 表達式 [ 表達式 ] |
(4) | ||||||||
& 與 * 相互抵銷,兩者皆不執行求值& 與 [] 中隱含的 * 相互抵銷,僅執行 [] 中隱含的加法運算。其中
| 左值表達式 | - | 任何非 位元欄位 且不具 暫存器 (register) 儲存類別的 左值 表達式 |
取址運算子會產生其運算元的 非左值 位址,適用於初始化指向該運算元型別的指標。若運算元是函式指示項 (1),結果為函式指標。若運算元是物件 (2),結果為物件指標。
若運算元是取值運算子,則不採取任何動作(因此對空指標使用 &* 是合法的),但結果不再是左值。
若運算元是陣列索引表達式,除了陣列轉指標轉換與加法外不採取其他動作,因此對於大小為 N 的陣列,&a[N] 是有效的(取得陣列末尾後一個位置的指標是合法的,對其取值則否,但此表達式中取值會被抵銷)。
int f(char c) { return c;} int main(void) { int n = 1; int *p = &n; // address of object n int (*fp)(char) = &f; // address of function f int a[3] = {1,2,3}; int *beg=a, *end=&a[3]; // same as end = a+3 }
[編輯] 成員存取
成員存取表達式的形式為
表達式 . 成員名稱 |
|||||||||
其中
| expression | - | struct 或 union 型別的表達式 |
| 成員名稱 | - | 一個 識別字,用以命名由 表達式 所指定的 struct 或 union 中的成員 |
成員存取表達式指定了由其左運算元所指定的 struct 或 union 的成員。它具有與其左運算元相同的 值類別 (value category)。
若左運算元具備 const 或 volatile 限定符,結果也具備相應限定符。若左運算元為 原子類型 (atomic),行為未定義。
注意:除了命名 struct 或 union 型別物件的識別字外,以下表達式也可能具有 struct 或 union 型別:賦值、函式呼叫、逗號運算子、條件運算子 以及 複合字面值。
#include <stdio.h> struct s {int x;}; struct s f(void) { return (struct s){1}; } int main(void) { struct s s; s.x = 1; // ok, changes the member of s int n = f().x; // f() is an expression of type struct s // f().x = 1; // Error: this member access expression is not an lvalue const struct s sc; // sc.x = 3; // Error: sc.x is const, can't be assigned union { int x; double d; } u = {1}; u.d = 0.1; // changes the active member of the union }
[編輯] 透過指標存取成員
成員存取表達式的形式為
表達式 -> 成員名稱 |
|||||||||
其中
| expression | - | 指向 struct 或 union 的 指標 型別之表達式 |
| 成員名稱 | - | 一個 識別字,用以命名由 表達式 所指向的 struct 或 union 中的成員 |
透過指標存取成員的表達式,指定了由其左運算元所指向的 struct 或 union 型別的成員。其值類別永遠為 左值。
若左運算元所指向的型別具備 const 或 volatile 限定符,結果也具備相應限定符。若左運算元所指向的型別為 原子類型 (atomic),行為未定義。
#include <stdio.h> struct s {int x;}; int main(void) { struct s s={1}, *p = &s; p->x = 7; // changes the value of s.x through the pointer printf("%d\n", p->x); // prints 7 }
[編輯] 缺陷報告
以下變更行為的缺陷報告已回溯應用於先前發佈的 C 標準。
| DR | 應用於 | 出版時的行為 | 正確的行為 |
|---|---|---|---|
| DR 076 | C89 | 不必要的間接運算無法被 & 抵銷 |
改為可抵銷 |
[編輯] 參考資料
- C17 標準 (ISO/IEC 9899:2018)
- 6.5.2.1 陣列下標 (p: 57-58)
- 6.5.2.3 結構與聯合體成員 (p: 58-59)
- 6.5.3.2 位址與間接運算子 (p: 59-61)
- C11 標準 (ISO/IEC 9899:2011)
- 6.5.2.1 陣列下標 (p: 80)
- 6.5.2.3 結構與聯合體成員 (p: 82-84)
- 6.5.3.2 位址與間接運算子 (p: 88-89)
- C99 標準 (ISO/IEC 9899:1999)
- 6.5.2.1 陣列下標 (p: 70)
- 6.5.2.3 結構與聯合體成員 (p: 72-74)
- 6.5.3.2 位址與間接運算子 (p: 78-79)
- C89/C90 標準 (ISO/IEC 9899:1990)
- 3.3.2.1 陣列下標
- 3.3.2.3 結構與聯合體成員
- 3.3.3.2 位址與間接運算子
[編輯] 參見
| 常用運算子 | ||||||
|---|---|---|---|---|---|---|
| 賦值 | 遞增 遞減 |
算術 | 邏輯 | 比較 | 成員 存取 |
其他 |
|
a = b |
++a |
+a |
!a |
a == b |
a[b] |
a(...) |
| C++ 文件 關於 成員存取運算子
|