メンバアクセス演算子
メンバアクセス演算子は被演算子のメンバへのアクセスを可能にします。
| 演算子 | 演算子の名前 | 例 | 説明 |
|---|---|---|---|
[]
|
配列の添字 | a[b]
|
配列 a の b 番目の要素にアクセスします。 |
*
|
ポインタの逆参照 | *a
|
参照先のオブジェクトまたは関数にアクセスするためにポインタ a を逆参照します。 |
&
|
アドレス取得 | &a
|
オブジェクトまたは関数 a を参照するポインタを作成します。 |
.
|
メンバアクセス | a.b
|
構造体または共用体 a のメンバ b にアクセスします。 |
->
|
ポインタを通したメンバアクセス | a->b
|
a の指す先の構造体または共用体のメンバ b にアクセスします。 |
添字
配列添字式は以下の形式を持ちます。
pointer-expression [ integer-expression ]
|
(1) | ||||||||
integer-expression [ pointer-expression ]
|
(2) | ||||||||
ただし、
| pointer-expression | - | 完全型へのポインタ型の式。 |
| integer-expression | - | 整数型の式。 |
添字演算子式は pointer-expression の指す先のオブジェクトの型を持つ左辺値式です。
定義により、添字演算子 E1[E2] は *((E1)+(E2)) と正確に同一です。 pointer-expression が配列式の場合は、左辺値から右辺値への変換が適用され、その配列の先頭の要素を指すポインタになります。
ポインタと整数の間の加算の定義により、結果は integer-expression の結果と等しいインデックスを持つ配列要素です (または、 pointer-expression が何らかの配列の i 番目を指していた場合は、結果のインデックスは i プラス integer-expression の結果です)。
ノート: 多次元配列の詳細については配列を参照してください。
#include <stdio.h>
int main(void)
{
int a[3] = {1,2,3};
printf("%d %d\n", a[2], // n == 3
2[a]); // 同上、 n == 3
a[2] = 7; // a[2] は左辺値です。
int n[2][3] = {1,2,3,4,5,6};
int (*p)[3] = &n[1]; // n の要素は配列です。
int x = n[1][2]; // 配列 n[1] に再度 [] を適用します。
printf("%c %c\n", "abc"[2], 2["abc"]); // 文字列リテラルも配列です。
}
出力:
3 3
c c
逆参照
逆参照または間接参照式は以下の形式を持ちます。
* pointer-expression
|
|||||||||
ただし
| pointer-expression | - | 任意のポインタ型の式。 |
pointer-expression が関数へのポインタの場合、逆参照演算子の結果はその関数に対する関数指示子です。
pointer-expression がオブジェクトへのポインタの場合、結果はその指す先のオブジェクトを指示する左辺値式です。
ヌルポインタ、生存期間外のオブジェクトへのポインタ (ダングリングポインタ)、または不定値を持つポインタの逆参照は、未定義動作です。 ただし、 &*E のように、結果にアドレス取得演算子を適用することによって逆参照演算子が無効化されるときは除きます。 (C99以上)
#include <stdio.h>
int main(void)
{
int n = 1;
int* p = &n;
printf("*p = %d\n", *p); // *p の値は n に格納されている値です。
*p = 7; // *p は左辺値です。
printf("*p = %d\n", *p);
}
出力:
*p = 1
*p = 7
アドレス取得
アドレス取得式は以下の形式を持ちます。
& function
|
(1) | ||||||||
& lvalue-expression
|
(2) | ||||||||
& * expression
|
(3) | (C99以上) | |||||||
& expression [ expression ]
|
(4) | (C99以上) | |||||||
ただし、
| lvalue-expression | - | ビットフィールドでなく、 register 記憶域クラスを持たない、任意の型の左辺値式。 |
アドレス取得演算子は被演算子のアドレスである非左辺値を生成します。 これはその被演算子の型へのポインタを初期化するのに適しています。 被演算子が関数指示子の場合 (1)、結果は関数へのポインタです。 被演算子がオブジェクトの場合 (2)、結果はオブジェクトへのポインタです。
|
被演算子が逆参照演算子の場合は、結果が左辺値でなくなることを除いて、何も行われません (そのため、ヌルポインタに &* を適用することは許されています)。 被演算子が配列添字式の場合は、配列からポインタへの変換と加算を除いて、何も行われません (そのため、サイズ N の配列に対して &a[N] は有効です (最後の要素の次の要素へのポインタを取得することは許されており、その逆参照は許されていませんが、この式では逆参照はキャンセルされます))。 |
(C99以上) |
int f(char c) { return c;}
int main(void)
{
int n = 1;
int *p = &n; // オブジェクト n のアドレス。
int (*fp)(char) = &f; // 関数 f のアドレス。
int a[3] = {1,2,3};
int *beg=a, *end=&a[3]; // end = n+3 と同じです。
}
メンバアクセス
メンバアクセス式は以下の形式を持ちます。
expression . member-name
|
|||||||||
ただし、
| expression | - | 構造体型または共用体型の式。 |
| member-name | - | expression によって指示される構造体または共用体のメンバを表す識別子。 |
メンバアクセス式はその左側の被演算子によって指示される構造体または共用体の名前付きメンバを指示します。 左側の被演算子と同じ値カテゴリを持ちます。
左側の被演算子が const または volatile 修飾されている場合、結果も修飾されます。 左側の被演算子がアトミックの場合、動作は未定義です。
ノート: 構造体型または共用体型の名前付きオブジェクトを表す識別子の他に、代入、関数呼び出し、コンマ演算子、条件演算子、および複合リテラルも構造体型または共用体型を持つことがあります。
#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、 s のメンバを変更します。
int n = f().x; // f() は struct s 型の式です。
// f().x = 1; // エラー、このメンバアクセス式は左辺値ではありません。
const struct s sc;
// sc.x = 3; // エラー、 sc.x は const です。 代入できません。
union { int x; double d; } u = {1};
u.d = 0.1; // 共用体のアクティブメンバを変更します。
}
ポインタを通したメンバアクセス
メンバアクセス式は以下の形式を持ちます。
expression -> member-name
|
|||||||||
ただし、
| expression | - | 構造体または共用体へのポインタ型の式。 |
| member-name | - | expression の指す先の構造体または共用体のメンバを表す識別子。 |
ポインタを通したメンバアクセス式は左側の被演算子の指す先の構造体型または共用体型の名前付きメンバを指示します。 値カテゴリは常に左辺値です。
左側の被演算子の指す先の型が const または volatile 修飾されている場合、結果も修飾されます。 左側の被演算子の指す先の型がアトミックの場合、動作は未定義です。
#include <stdio.h>
struct s {int x;};
int main(void)
{
struct s s={1}, *p = &s;
p->x = 7; // ポインタを通して s.x の値を変更します。
printf("%d\n", p->x); // 7 を表示します。
}
参考文献
- C11 standard (ISO/IEC 9899:2011):
- 6.5.2.1 Array subscripting (p: 80)
- 6.5.2.3 Structure and union members (p: 82-84)
- 6.5.3.2 Address and indirection operators (p: 88-89)
- C99 standard (ISO/IEC 9899:1999):
- 6.5.2.1 Array subscripting (p: 70)
- 6.5.2.3 Structure and union members (p: 72-74)
- 6.5.3.2 Address and indirection operators (p: 78-79)
- C89/C90 standard (ISO/IEC 9899:1990):
- 3.3.2.1 Array subscripting
- 3.3.2.3 Structure and union members
- 3.3.3.2 Address and indirection operators
関連項目
| 一般的な演算子 | ||||||
|---|---|---|---|---|---|---|
| 代入 | インクリメント デクリメント |
算術 | 論理 | 比較 | メンバアクセス | その他 |
|
|
|
|
|
|
|
|
メンバアクセス演算子 の C++リファレンス
|