Assignment operators
代入演算子と複合代入演算子は、右側の値を使用して左側の変数を変更する二項演算子です。
| 演算子 | 演算子名 | 例 | 説明 | 等価表現 |
|---|---|---|---|---|
| = | 基本代入 | a = b | a が b と等しくなる | 該当なし |
| + = | 加算代入 | a + = b | a が a と b の加算結果と等しくなる | a = a + b |
| - = | 減算代入 | a - = b | a が a から b を減算した結果と等しくなる | a = a - b |
| * = | 乗算代入 | a * = b | a が a と b の積と等しくなる | a = a * b |
| / = | 除算代入 | a / = b | a が a を b で除算した結果と等しくなる | a = a / b |
| % = | 剰余代入 | a % = b | a が a を b で除算した余りと等しくなる | a = a % b |
| & = | ビット単位AND代入 | a & = b | a が a と b のビット単位ANDと等しくなる | a = a & b |
| | = | ビット単位OR代入 | a | = b | a が a と b のビット単位ORと等しくなる | a = a | b |
| ^ = | ビット単位XOR代入 | a ^ = b | a が a と b のビット単位XORと等しくなる | a = a ^ b |
| <<= | ビット単位左シフト代入 | a <<= b | a が a を b ビット左シフトした値と等しくなる | a = a << b |
| >>= | ビット単位右シフト代入 | a >>= b | a が a を b ビット右シフトした値と等しくなる | a = a >> b |
目次 |
単純代入
単純代入演算子の式は以下の形式を持ちます
lhs
=
rhs
|
|||||||||
ここで
| lhs | - | 変更可能な左辺値 任意の完全オブジェクト型の式 |
| rhs | - | 任意の型の式 暗黙的に変換可能 で lhs に、または 互換性のある lhs |
代入は 暗黙変換 を実行し、 rhs の値から lhs の型へ変換した後、 lhs で指定されるオブジェクトの値を rhs の変換された値で置き換えます。
代入はまた、
lhs
に格納された値と同じ値を返します(これにより、
a
=
b
=
c
のような式が可能となります)。代入演算子の
値カテゴリ
は非左辺値です(これにより、
(
a
=
b
)
=
c
のような式は無効となります)。
rhs と lhs は以下のいずれかを満たす必要があります:
-
- lhs と rhs の両方が 算術型 を持つ場合。この場合 lhs は volatile 修飾されている可能性がある または atomic (C11以降)
- lhs と rhs の両方が ポインタ 型(修飾子を無視して) 互換性のある 型を指している場合、または一方のポインタがvoidへのポインタであり、 変換 によって指し示される型に修飾子が追加されない場合。 lhs は volatile または restrict (C99以降) 修飾されている可能性がある または atomic (C11以降) 。
- lhs が(修飾されている可能性がある またはatomic (C11以降) )ポインタであり、 rhs が NULL または nullptr_t 値 (C23以降) のようなヌルポインタ定数である場合
|
(C99以降) |
| (C23以降) |
注記
rhs と lhs がメモリ上で重複している場合(例:同じunionのメンバである場合)、その重複が正確でかつ型が 互換性がある 場合を除き、動作は未定義です。
配列は代入可能ではありませんが、構造体でラップされた配列は、同じ(または互換性のある)構造体型の別のオブジェクトに代入可能です。
lhs を更新する副作用は、値計算の 後に順序付けられます が、 lhs および rhs 自体の副作用は含まれず、オペランドの評価は通常通り互いに順序付けられていません(したがって、 i = ++ i のような式は未定義です)
代入は浮動小数点式から余分な範囲と精度を取り除きます( FLT_EVAL_METHOD を参照)。
C++では、代入演算子は左辺値式ですが、Cではそうではありません。
#include <stdio.h> int main(void) { // 整数 int i = 1, j = 2, k = 3; // 初期化、代入ではない i = j = k; // iとjの値は現在3 // (i = j) = k; // エラー: 左辺値が必要 printf("%d %d %d\n", i, j, k); // ポインタ const char c = 'A'; // 初期化; 代入ではない const char *p = &c; // 初期化; 代入ではない const char **cpp = &p; // 初期化; 代入ではない // cpp = &p; // エラー: char** は const char** に変換できない *cpp = &c; // OK, char* は const char* に変換可能 printf("%c \n", **cpp); cpp = 0; // OK, ヌルポインタ定数は任意のポインタに変換可能 // 配列 int arr1[2] = {1,2}, arr2[2] = {3, 4}; // arr1 = arr2; // エラー: 配列に代入できない printf("arr1[0]=%d arr1[1]=%d arr2[0]=%d arr2[1]=%d\n", arr1[0], arr1[1], arr2[0], arr2[1]); struct { int arr[2]; } sam1 = { {5, 6} }, sam2 = { {7, 8} }; sam1 = sam2; // OK: 構造体でラップされた配列は代入可能 printf("%d %d \n", sam1.arr[0], sam1.arr[1]); }
出力:
3 3 3 A arr1[0]=1 arr1[1]=2 arr2[0]=3 arr2[1]=4 7 8
複合代入
複合代入演算子の式は以下の形式を持ちます
| lhs op rhs | |||||||||
ここで
| op | - | 次のいずれか * = , / = % = , + = - = , <<= , >>= , & = , ^ = , | = |
| lhs , rhs | - | 算術型 を持つ式( lhs は修飾またはアトミック型でも可)。 op が + = または - = の場合、+および-演算子と同じ制限を持つポインタ型も受け入れる |
式
lhs
@=
rhs
は、
lhs
=
lhs
@
(
rhs
)
と完全に同じですが、
lhs
が一度だけ評価される点が異なります。
|
lhs が atomic 型を持つ場合、この操作はメモリ順序 memory_order_seq_cst を持つ単一のアトミックな読み込み-変更-書き込み操作として振る舞います。 整数アトミック型の場合、複合代入 @ = は以下と同等です: T1* addr = &lhs; T2 val = rhs; T1 old = *addr; T1 new; do { new = old @ val } while (!atomic_compare_exchange_strong(addr, &old, new); |
(C11以降) |
出力:
10 100 10 50 10 1000 1 0
参考文献
- C17規格 (ISO/IEC 9899:2018):
-
- 6.5.16 代入演算子 (p: 72-73)
- C11規格 (ISO/IEC 9899:2011):
-
- 6.5.16 代入演算子 (p: 101-104)
- C99規格 (ISO/IEC 9899:1999):
-
- 6.5.16 代入演算子 (p: 91-93)
- C89/C90標準 (ISO/IEC 9899:1990):
-
- 3.3.16 代入演算子
関連項目
| 一般的な演算子 | ||||||
|---|---|---|---|---|---|---|
| 代入 |
インクリメント
デクリメント |
算術 | 論理 | 比較 |
メンバー
アクセス |
その他 |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
b
]
|
a
(
...
)
|
関連項目
|
C++ documentation
for
Assignment operators
|