名前空間
変種
操作

代入演算子

From cppreference.com
< c‎ | language

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

Operator 演算子名 説明 相当するもの
= 単純代入 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
&= ビットAND代入 a &= b aab のビットごとのAND結果と等しくなる a = a & b
|= ビットOR代入 a |= b aab のビットごとのOR結果と等しくなる a = a | b
^= ビットXOR代入 a ^= b aab のビットごとのXOR結果と等しくなる a = a ^ b
<<= ビット左シフト代入 a <<= b aab ビット左シフトした結果と等しくなる a = a << b
>>= ビット右シフト代入 a >>= b aab ビット右シフトした結果と等しくなる a = a >> b

目次

[編集] 単純代入

単純代入演算子式は、次の形式をとります。

lhs = rhs

ここで、

lhs - あらゆる完全なオブジェクト型の変更可能な左辺値式
rhs - lhs に暗黙的に変換可能、または lhs と互換性のある、あらゆる型の式

代入は、rhs の値から lhs の型への暗黙的な変換を実行し、その後 lhs が指定するオブジェクトの値を rhs の変換された値で置き換えます。

代入は、lhs に格納された値と同じ値を返します(たとえば、a = b = c のような式が可能です)。代入演算子の値カテゴリは左辺値ではありません(したがって、(a=b)=c のような式は無効です)。

rhslhs は、次のいずれかの条件を満たす必要があります。

  • 両方の lhsrhs が互換性のある構造体または共用体型である、または...
  • rhslhs に暗黙的に変換可能でなければならず、これは以下を意味します。
  • 両方の lhsrhs が算術型であり、この場合 lhs は volatile修飾されていてもかまいません(C11以降、またはatomicでもかまいません)。
  • 両方の lhsrhs が互換性のある(修飾子を無視した)型のポインタであり、または一方のポインタが void へのポインタであり、変換によってポインタ先型に修飾子が付加されない場合。 lhs は volatile(C99以降、またはrestrictでもかまいません)修飾されていてもかまいません(C11以降、またはatomicでもかまいません)。
  • lhs は(修飾子またはatomicであってもよい)ポインタであり、rhs はヌルポインタ定数(例: NULL、C23以降、またはnullptr_t 値)である。
  • lhs は _Bool 型(修飾子またはatomicであってもよい)であり、rhs はポインタ(C23以降、またはnullptr_t 値)である。
(C99以降)
  • lhs は nullptr_t 型(修飾子またはatomicであってもよい)であり、rhs は nullptr_t 型である。
(C23以降)

[編集] 注記

rhslhs がメモリ上で重複している場合(例: 同じ共用体のメンバーである場合)、重複が完全に一致し、型が互換性がない限り、未定義の動作となります。

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

lhs を更新する副作用は、値の計算よりも後続します。ただし、lhsrhs 自身の副作用やオペランドの評価は、通常どおり、互いに順序付けられていません(そのため、i=++i; のような式は未定義です)。

代入は、浮動小数点式から余分な範囲と精度を削除します(FLT_EVAL_METHOD を参照)。

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

#include <stdio.h>
 
int main(void)
{
    // integers
    int i = 1, j = 2, k = 3; // initialization, not assignment
 
    i = j = k;   // values of i and j are now 3
//  (i = j) = k; // Error: lvalue required
    printf("%d %d %d\n", i, j, k);
 
    // pointers
    const char c = 'A'; // initialization; not assignment
    const char *p = &c;  // initialization; not assignment
    const char **cpp = &p; // initialization; not assignment
 
//  cpp = &p;   // Error: char** is not convertible to const char**
    *cpp = &c;  // OK, char* is convertible to const char*
    printf("%c \n", **cpp);
    cpp = 0;    // OK, null pointer constant is convertible to any pointer
 
    // arrays
    int arr1[2] = {1,2}, arr2[2] = {3, 4};
//  arr1 = arr2; // Error: cannot assign to an array
    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: can assign arrays wrapped in structs
 
    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 は修飾子またはatomicであってもよい)。ただし、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 以降)
#include <stdio.h>
 
int main(void)
{
    int x = 10; 
    int hundred = 100; 
    int ten = 10; 
    int fifty = 50; 
 
    printf("%d %d %d %d\n", x, hundred, ten, fifty);
 
    hundred *= x; 
    ten     /= x; 
    fifty   %= x; 
 
    printf("%d %d %d %d\n", x, hundred, ten, fifty);
 
    return 0;
}

出力

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 += 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
a ? b : c
sizeof


_Alignof
(C11 以降)
(C23まで)

alignof
(C23以降)

[編集] 関連項目

C++ドキュメント (代入演算子)
English 日本語 中文(简体) 中文(繁體)