命名空間
變體
動作

成員存取運算子

出自 cppreference.com
< c‎ | 語言

成員存取運算子允許存取其運算元的成員。

運算子 運算子名稱 範例 描述
[] 陣列下標 a[b] 存取陣列 a 的第 b 個元素
* 指標取值 (dereference) *a 對指標 a 取值,以存取其所指涉的物件或函式
& 取址 &a 建立一個指涉物件或函式 a 的指標
. 成員存取 a.b 存取 structunion a 的成員 b
-> 透過指標存取成員 a->b 存取由 a 所指之 structunion 的成員 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

#include <stdio.h>
int main(void)
{
    int n = 1;
    int* p = &n;
    printf("*p = %d\n", *p); // the value of *p is what's stored in n
    *p = 7; // *p is lvalue
    printf("*p = %d\n", *p);
}

輸出

*p = 1
*p = 7

[編輯] 取址

取址表達式的形式為

& 函式 (1)
& 左值表達式 (2)
& * 表達式 (3)
& 表達式 [ 表達式 ] (4)
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 - structunion 型別的表達式
成員名稱 - 一個 識別字,用以命名由 表達式 所指定的 struct 或 union 中的成員

成員存取表達式指定了由其左運算元所指定的 structunion 的成員。它具有與其左運算元相同的 值類別 (value category)

若左運算元具備 constvolatile 限定符,結果也具備相應限定符。若左運算元為 原子類型 (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 - 指向 structunion指標 型別之表達式
成員名稱 - 一個 識別字,用以命名由 表達式 所指向的 struct 或 union 中的成員

透過指標存取成員的表達式,指定了由其左運算元所指向的 structunion 型別的成員。其值類別永遠為 左值

若左運算元所指向的型別具備 constvolatile 限定符,結果也具備相應限定符。若左運算元所指向的型別為 原子類型 (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 += b
a -= b
a *= b
a /= b
a %= b
a &&= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b

a[b]
*a
&a
a->b
a.b

a(...)
a, b
(型別) a
a ? b : c
sizeof


_Alignof
(自 C11 起)
(C23 之前)

alignof
(C23 起)

C++ 文件 關於 成員存取運算子
English Deutsch 日本語 中文(简体) 中文(繁體)