名前空間
変種
操作

代入演算子

提供: cppreference.com
< c‎ | language

代入および複合代入演算子は右辺の値を使用して左辺の変数を変更する二項演算子です。

演算子 演算子の名前 説明 同等な式
= 単純代入 a = b ab に等しくなります。 N/A
+= 加算代入 a += b aab の和に等しくなります。 a = a + b
-= 減算代入 a -= b aa から b を引いた差に等しくなります。 a = a - b
*= 乗算代入 a *= b aab の積に等しくなります。 a = a * b
/= 除算代入 a /= b aab で割った商に等しくなります。 a = a / b
%= 剰余代入 a %= b aab で割った余りに等しくなります。 a = a % b
&= ビット単位の論理積代入 a &= b aab のビット単位の論理積に等しくなります。 a = a & b
|= ビット単位の論理和代入 a |= b aab のビット単位の論理和に等しくなります。 a = a | b
^= ビット単位の排他的論理和代入 a ^= b aab のビット単位の排他的論理和に等しくなります。 a = a ^ b
<<= ビット単位の左シフト代入 a <<= b aab ビットの左シフトに等しくなります。 a = a << b
>>= ビット単位の右シフト代入 a >>= b aab ビットの右シフトに等しくなります。 a = a >> b

目次

[編集] 単純代入

単純代入演算子式は以下の形式を持ちます。

lhs = rhs

ただし、

lhs - 任意の完全オブジェクト型の変更可能な左辺値式。
rhs - lhs または lhs互換な型に暗黙に変換可能な型の式。

代入は rhs の値から lhs の型への暗黙の変換を行い、その変換後の値で lhs の指示するオブジェクトの値を置き換えます。

また、代入は lhs に格納されたのと同じ値を返します (そのため a = b = c のような式が書けます)。 代入演算子の値カテゴリは非左辺値です (そのため (a=b)=c のような式は無効です)。

rhs および lhs は以下のいずれかを���たさなければなりません。

  • lhsrhs がどちらも算術型である。 この場合、 lhsvolatile 修飾されていても構いませんしアトミックでも構いません。
  • lhsrhs がどちらも互換 (修飾は無視します) な型へのポインタ型である。 または、ポインタの一方が void へのポインタであり、指す先の型に修飾を追加しない。 lhsvolatile または restrict 修飾されていても構いませんし、アトミックでも構いません。
  • lhs がポインタ (修飾されていても構いません) (アトミックでも構いません) であり、 rhs がヌルポインタ (NULL など) である。
  • lhs_Bool 型 (修飾されていても構いません) (アトミックでも構いません) であり、 rhs がポインタである。

[編集] ノート

rhslhs がメモリ内でオーバーラップしている場合 (例えば同じ共用体のメンバであるとか)、そのオーバーラップが正確であり型が互換でない限り、動作は未定義です。

配列は代入可能ではありませんが、構造体に包まれた配列は同じ (または互換な) 構造体型の別のオブジェクトに代入可能です。

rhs の値計算は lhs を更新する副作用に対して先行配列されますが、 lhs および rhs の副作用それ自体はそうではなく、被演算子の評価は、通常通り、お互い、相対的に配列されません (そのため i=++i のような式は未定義です)。

代入は浮動小数点式から余分な範囲および精度を取り除きます (FLT_EVAL_METHOD を参照してください)。

C++ では代入演算子は左辺値式ですが、 C ではそうではありません。

#include <stdio.h>
 
int main(void)
{
    const char **cpp;
    char *p;
    const char c = 'A';
 
//  cpp = &p;  // エラー、 char** は const char** に変換可能でありません。
    *cpp = &c; // OK、 char* は const char* に変換可能です。
    *p = 0;    // OK、ヌルポインタ定数は任意のポインタに変換可能です。
 
    int arr1[2] = {1,2}, arr2[2] = {3, 4};
//  arr1 = arr2; // エラー、配列は代入できません。
 
    struct s { 
         int arr[2]; // 構造体に包まれた配列
    } sam1 = {5, 6}, sam2 = {7, 8};
    sam1 = sam2; // OK、構造体に包まれた配列は代入できます。
 
    printf("%d %d \n",sam1.arr[0],sam1.arr[1]);
}

出力:

7 8

[編集] 複合代入

複合代入演算子式は以下の形式を持ちます。

lhs op rhs

ただし、

op - *=/= %=+= -=<<=>>=&=^=|= のいずれか。
lhs, rhs - 算術型の式 (lhs は修飾されていても構いません) (lhs はアトミックでも構いません)。 ただし op+= または -= のときは + および - と同じ制約付きでポインタ型も受理します。

lhs @= rhs は、 lhs が一度しか評価されないことを除いて、 lhs = lhs @ ( rhs ) と正確に同じです。

lhsアトミック型の場合、演算は 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以上)

[編集] 参考文献

  • C11 standard (ISO/IEC 9899:2011):
  • 6.5.16 Assignment operators (p: 101-104)
  • C99 standard (ISO/IEC 9899:1999):
  • 6.5.16 Assignment operators (p: 91-93)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 3.3.16 Assignment operators

[編集] 関連項目

演算子の優先順位

一般的な演算子
代入 インクリメント
デクリメント
算術 論理 比較 メンバアクセス その他

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
(type) a
? :
sizeof
_Alignof
(C11以上)

代入演算子C++リファレンス