C言語/演算子と式
演算子と式の基本
編集演算子とは演算の内容を指示する記号です。 式とは定数、変数、関数の返却値などを演算子を使って結合したものです。
演算子には優先順位があります。 次の表の優先順位は、その演算子の優先順位を表しています。 演算子は優先順位が高いものから評価されます。 例えば「1+2*3」の場合は、「4.加減演算子」より「3.乗除演算子」の方が優先順位が高いので、「3.乗除演算子」が先に評価され、値は「7」となります。
演算子には結合規則(結合性)があります。 次の表の結合規則は、「→(左から右、左結合)」と「←(右から左、右結合)」とで結合の方向を表しています。 演算子の優先順位が同じ優先順位の場合は、結合規則の方向に演算が行われます。 例えば「a=b=1」の場合は、「14.代入演算子」は「←(右から左、右結合)」なので「b=1」が先に行われ、aとbの値はともに「1」となります。
数学と同様に()で囲むことにより優先させることができます。
オペランドとは、演算子が操作を行う対象のことであり、 定数、変数、関数の返却値、及びオペランドと演算子の組み合わせなどがオペランドとなりえます。
オペランドのデータ型は、より大きなオペランドのデータ型に変換されます(暗黙の型変換)[1][2]。
優先順位 | 演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|---|
1.後置式 | 配列の添字付け | [] | 添字演算子[] | 配列オブジェクトの要素の添字による指定。 | → |
関数呼び出し | () | 関数呼び出し | 関数呼び出し。 | ||
構造体及び共用体のメンバー | . | .演算子 | 構造体又は共用体オブジェクトの一つのメンバー。 | ||
-> | ->演算子 | 構造体又は共用体オブジェクトの一つのメンバー。 | |||
後置増分及び後置減分演算子 | ++ | 後置++演算子 | 左オペランドが指す変数の値を返した後、その変数の値に1を加えます。 | ||
-- | 後置--演算子 | 左オペランドが指す変数の値を返した後、その変数の値から1を引く。 | |||
複合リテラル | (型名){初期化子並び} | 複合リテラル | 初期化子並びで与えられる値を持つ名前のないオブジェクト | ||
2.単項演算子 キャスト演算子 |
前置増分及び前置減分演算子 | ++ | 前置++演算子 | 右オペランドが指す変数の値に1を加え、その変数の値を返す。 | ← |
-- | 前置--演算子 | 右オペランドが指す変数の値から1を引き、その変数の値を返す。 | |||
アドレスおよび間接演算子 | & | 単項&演算子 | 右オペランドのアドレスを返す。 | ||
* | 単項*演算子 | 右オペランドの間接参照を表す。 | |||
単項算術演算子 | + | 単項+演算子 | 右オペランドの値 | ||
- | 単項-演算子 | 右オペランドの符号を反転した値 | |||
単項算術演算子 | ~ | ~演算子 | 右オペランドのビット単位の補数 | ||
単項算術演算子 | ! | 論理否定演算子! | 右オペランドの否定 (右オペランドの値を0と比較し、等しい場合は1、等しくない場合は0) | ||
sizeof演算子 | sizeof(型名) sizeof(式) |
sizeof演算子 | オペランドの大きさ(バイト数) | ||
_Alignof演算子 | _Alignof(型名) | _Alignof演算子 | オペランドのアライメント要件(バイト数) | ||
キャスト演算子 | (データ型)式 | キャスト演算子 | 式の値を指定された型に型変換した値を返す。 | ||
3.乗除演算子 | 乗除演算子 | * | 2項*演算子 | 左右オペランドの積 | → |
/ | 2項/演算子 | 左オペランドを右オペランドで除した商 右オペランドの値が0の場合、その動作は未定義です。 左右オペランドが整数型の場合、商の小数部は切り捨てられます。 | |||
% | 2項%演算子 | 左オペランドを右オペランドで除した剰余 右オペランドの値が0の場合、その動作は未定義です。 左右オペランドは整数型でなければなりません。 | |||
4.加減演算子 | 加減演算子 | + | 2項+演算子 | 左右オペランドの和 | |
- | 2項-演算子 | 左オペランドから右オペランドを引いた差 | |||
5.ビット単位のシフト演算子 | ビット単位のシフト演算子 | << | <<演算子 | 左オペランドを右オペランドビット分左にシフトした値。 空いたビットには0を詰めます。 | |
>> | >>演算子 | 左オペランドを右オペランドビット分右にシフトした値。 | |||
6.関係演算子 | 関係演算子 | < | <演算子 | 左オペランドが右オペランドより小さい場合は1、それ以外の場合は0 | |
> | >演算子 | 左オペランドが右オペランドより大きい場合は1、それ以外の場合は0 | |||
<= | <=演算子 | 左オペランドが右オペランド以下の場合は1、それ以外の場合は0 | |||
>= | >=演算子 | 左オペランドが右オペランド以上の場合は1、それ以外の場合は0 | |||
7.等価演算子 | 等価演算子 | == | ==演算子 | 左右オペランド同士を比較し、等しい場合は1、それ以外の場合は0 | |
!= | !=演算子 | 左右オペランド同士を比較し、等しくない場合は1、それ以外の場合は0 | |||
8.ビット単位のAND演算子 | ビット単位のAND演算子 | & | 2項&演算子 | 両オペランドのビット単位の論理積 | |
9.ビット単位の排他OR演算子 | ビット単位の排他OR演算子 | ^ | ^演算子 | 両オペランドのビット単位の排他的論理和 | |
10.ビット単位のOR演算子 | ビット単位のOR演算子 | | | 演算子 | 両オペランドのビット単位の論理和 | |
11.論理AND演算子 | 論理AND演算子 | && | &&演算子 | 左右オペランドの論理積 (左右オペランドの値を0と比較し、ともに等しくない場合は1、それ以外の場合は0) | |
12.論理OR演算子 | 論理OR演算子 | || | ||演算子 | 左右オペランドの論理和 (左右オペランドの値を0と比較し、いずれか一方でも等しくない場合は1、それ以外の場合は0) | |
13.条件演算子 | 条件演算子 | 式1 ? 式2 : 式3 | 条件演算子 | 式1が0と比較して等しい場合式2を評価し、等しくない場合式3を評価します。 | ← |
14.代入演算子 | 単純代入 | = | 単純代入演算子 | 左オペランドが指す変数に右オペランドの値を格納する 代入後の左オペランドの値 | |
複合代入 | *= | *=演算子 | 形式E1 op= E2の複合代入は、 左辺値E1がただ一回だけ評価される点を除いて、 単純代入式E1 = E1 op (E2)と同じとします。 | ||
/= | /=演算子 | ||||
%= | %=演算子 | ||||
+ = | +=演算子 | ||||
-= | -=演算子 | ||||
<<= | <<=演算子 | ||||
>>= | >>=演算子 | ||||
&== | &=演算子 | ||||
^= | ^=演算子 | ||||
|= | |=演算子 | ||||
15.コンマ演算子 | コンマ演算子 | , | コンマ演算子 | 左オペランドをボイド式として評価し、次に右オペランドを評価しそれを結果として返す。 | → |
算術演算子と代入演算子
編集算術演算子とは加減乗除などの算術的な計算を行う演算子です。
算術演算子には、加法を指示する+
、減法を指示する-
[3]、
乗法を指示する*
、除法を指示する/
および剰余を指示する%があり[4]、
また、-
は符号の反転を指示するためにも用いられる[5]。
代入演算子とは代入を指示する演算子です。
代入演算子には右辺の値を左辺が指す変数へそのまま代入するように指示する=があります[6]。
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
単項演算子 | + | 単項+演算子 | 右オペランドの値 | ← |
- | 単項-演算子 | 右オペランドの符号を反転した値 | ← | |
乗除演算子 | * | 2項*演算子 | 左右オペランドの積 | → |
/ | 2項/演算子 | 左オペランドを右オペランドで除した商 右オペランドの値が0の場合、その動作は未定義です。 左右オペランドが整数型の場合、商の小数部は切り捨てられます。 |
→ | |
% | 2項%演算子 | 左オペランドを右オペランドで除した剰余 右オペランドの値が0の場合、その動作は未定義です。 左右オペランドは整数型でなければなりません。 |
→ | |
加減演算子 | + | 2項+演算子 | 左右オペランドの和 | → |
- | 2項-演算子 | 左オペランドから右オペランドを引いた差 | → | |
代入演算子 | = | 単純代入演算子 | 左オペランドが指す変数に右オペランドの値を格納する 代入後の左オペランドの値 |
← |
//例 変数に算術演算子を用いた式の値を、代入演算子を用いて代入します。
int main(void)
{
int i = -1; // iを-1で初期化します。
i = 1 * 1; // iに1×1である1を代入します。
i = 1 / 1; // iに1÷1である1を代入します。
i = 1 % 1; // iに1÷1の余りである0を代入します。
i = 1 + 1; // iに1+1である2を代入します。
i = 1 - 1; // iに1-1である0を代入します。
}
- C言語に冪乗演算子はありません。
^
は、ビット単位の排他的論理和演算子です。 - 平方根
- 浮動小数点数の剰余
比較演算子
編集比較演算子とは、左辺と右辺の比較を指示する演算子です。 比較演算子は左辺が右辺と比較して、 「<(より小さい)」、「>(より大きい)」「<=(以下)」「>=(以上)」 「==(等しい)」「!=(等しくない)」の場合は真(1)を、 それ以外の場合は偽(0)を、値として返す。 [7] [8]
C99で、true や false など論理値定数とのbool(論理型)が追加されました。
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
関係演算子 | < | <演算子 | 左オペランドが右オペランドより小さい場合は1、それ以外の場合は0 | → |
> | >演算子 | 左オペランドが右オペランドより大きい場合は1、それ以外の場合は0 | → | |
<= | <=演算子 | 左オペランドが右オペランド以下の場合は1、それ以外の場合は0 | → | |
>= | >=演算子 | 左オペランドが右オペランド以上の場合は1、それ以外の場合は0 | → | |
等価演算子 | == | ==演算子 | 左右オペランド同士を比較し、等しい場合は1、それ以外の場合は0 | → |
!= | !=演算子 | 左右オペランド同士を比較し、等しくない場合は1、それ以外の場合は0 | → |
//例 変数に比較演算子を用いた式の値を、代入演算子を用いて代入します。
#include <stdbool.h>
int main(void) {
bool r; // 変数 r を論理型として宣言
r = 10 < 20; // true
r = 10 > 20; // false
r = 10 <= 20; // true
r = 10 >= 20; // false
r = 10 == 20; // false
r = 10 != 20; // true
}
論理演算子
編集論理演算子とは、論理値の計算を指示する演算子です。 論理演算子には否定を指示する!、[9] 論理積を指示する&&、[10] 論理和を指示する||があります。[11]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
単項演算子 | ! | 論理否定演算子! | 右オペランドの否定 (右オペランドの値を0と比較し、等しい場合は1、等しくない場合は0) |
← |
論理AND演算子 | && | &&演算子 | 左右オペランドの論理積 (左右オペランドの値を0と比較し、ともに等しくない場合は1、それ以外の場合は0) |
→ |
論理OR演算子 | || | ||演算子 | 左右オペランドの論理和 (左右オペランドの値を0と比較し、いずれか一方でも等しくない場合は1、それ以外の場合は0) |
→ |
否定とは論理値の真と偽を入れ替えることを表す。 論理積とは左右両方の論理値がともに真であるときのみ真(1)を、それ以外は偽(0)を値として返す。 論理和とは左右両方の論理値のうちいずれか一方でも真であるとき真(1)を、それ以外は偽(0)を値として返す。
p | q | !p 否定 |
p&&q 論理積 |
p||q 論理和 |
---|---|---|---|---|
0 | 0 | 1 | 0 | 0 |
0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 0 | 1 |
1 | 1 | 0 | 1 | 1 |
//例 変数に論理演算子を用いた式の値を、代入演算子を用いて代入します。
int main(void) {
int r;
r = !0; // rに1を代入します。
r = 0 && 1; // rに0を代入します。
r = 0 || 1; // rに1を代入します。
}
短絡評価
編集&&演算子と||演算子とは、短絡評価を行う。 短絡評価とは、第1オペランドの値でその式の値が決まるとき、第2オペランドを評価しないことです。 &&演算子は第1オペランドの値が偽(0)の時、第2オペランドを評価しません。 ||演算子は第1オペランドの値が真(0以外)の時、第2オペランドを評価しません。 短絡評価は、第2オペランドに副作用を伴う式を指定したとき、特に注意が必要です。 つまり、第2オペランドに関数呼び出しの式を指定して、短絡評価が行われた時、 その関数呼び出しは実行されません。
排他的論理和
編集C言語には、排他的論理和の論理演算子は定義されていません。 しかし、排他的論理和は、否定・論理積・論理和を用いて次のように記述できます。
(!p != !q)
(p && !q) || (!p && q)
(p || q) && (!p || !q)
(p || q) && !(p && q)
排他的論理和とは、2つの論理値のいずれかただ1つのみが真であるとき真(1)を、それ以外は偽(0)を値として返す。
p | q | p xor q 排他的論理和 |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
増分及び減分演算子
編集増分及び減分演算子とは、変数の値に1を加えたり、1を引いたりすることを指示する演算子です。 増分及び減分演算子には、それぞれ後置演算子と前置演算子とがあります。 後置演算子は変数の値を返した後に、増減を行う。[12] 前置演算子は変数の値を返す前に、増減を行う。[13]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
後置演算子 | ++ | 後置++演算子 | 左オペランドが指す変数の値を返した後、その変数の値に1を加えます。 | → |
-- | 後置--演算子 | 左オペランドが指す変数の値を返した後、その変数の値から1を引く。 | → | |
単項演算子 | ++ | 前置++演算子 | 右オペランドが指す変数の値に1を加え、その変数の値を返す。 | ← |
-- | 前置--演算子 | 右オペランドが指す変数の値から1を引き、その変数の値を返す。 | ← |
増分及び減分演算子を単独で用いた場合、後置と前置との結果に違いはありません。
//例 後置++演算子を単独で用います。
int main(void) {
int i = 0;
i++; // iには1が格納されます。
}
//例 前置++演算子を単独で用います。
int main(void) {
int i = 0;
++i; // iには1が格納されます。
}
ただし、増分及び減分演算子を代入演算子とともに用いた場合、後置と前置との結果に違いがあります。
//例 後置++演算子を代入演算子とともに用います。
int main(void) {
int i = 0;
int j;
j = i++; // iには1が格納され、jには0が格納されます。
}
//例 前置++演算子を代入演算子とともに用います。
int main(void) {
int i = 0;
int j;
j = ++i; // iには1が格納され、jには1が格納されます。
}
その他の演算子
編集複合リテラル
編集ISO/IEC 9899:2017§6.5.2.5 Compound literals
括弧で囲まれた型名の後に、ブレースで囲まれた初期化子並び( initializer lists )を続けた後置式( postfix expression)[14]は、複合リテラル(ふくごう- 、Compound literals)です[15]。
- ( type-name ) { initializer-list }
- ( type-name ) { initializer-list , }
複合リテラルは、初期化子並びで与えられる値を持つ名前のないオブジェクトを与えます[15]。 型名が未知のサイズの配列を指定している場合、そのサイズは初期化子並びによって決定され、複合リテラルの型は完成した配列の型になります。それ以外の場合(型名がオブジェクト型を指定している場合)は,型名で指定された型が複合リテラルの型となります。いずれの場合も結果は左辺値です[15]。 複合リテラルの値は、初期化子並びで初期化された無名のオブジェクトの値です。複合リテラルが関数本体の外にある場合、そのオブジェクトは静的な保存期間を持ちますが、そうでない場合は、囲んでいるブロックに関連付けられた自動保存期間を持ちます[15]。 初期化子並びに関するすべての意味的規則は、複合リテラルにも適用されます[15]。 文字列リテラル、およびconst修飾された型を持つ複合リテラルは、異なるオブジェクトを指定する必要はありません[15]。
関数の引数に定数として構造体を渡したいとき、変数を宣言して値を代入し、それを渡す必要があります。
- 構造体変数を関数に渡す
#include <stdio.h> struct sPoint { int x, y; }; void DrawPoint(const struct sPoint *p) { printf("%d %d\n", p->x, p->y); } int main(void) { struct sPoint p = { 200, 100 }; DrawPoint(&p); }
- 複合リテラルを使えば上の処理をより簡潔に下のように書くことができます。
- 複合リテラルを引数として関数に渡す
#include <stdio.h> struct sPoint { int x, y; }; void DrawPoint(const struct sPoint *p) { printf("%d %d\n", p->x, p->y); } int main(void) { DrawPoint(&(struct sPoint){.x = 200, .y = 100}); // あるいは DrawPoint(&(struct sPoint){200, 100}); }
- 配列の複合リテラル
#include <stdio.h> int main(void) { for (int *ip = (int[]){ 2, 3, 5, 7, 11, -1}; *ip > 0; ip++) printf("%d\n", *ip); }
- 実行結果
2 3 5 7 11
- 文字列の複合リテラル
#include <stdio.h> int main(void) { puts((char []){'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '\n', 0}); }
sizeof演算子
編集sizeof演算子とは、オペランドの大きさ(バイト数: 型は size_t)を返す演算子です。[16]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
単項演算子 | sizeof(型名) | sizeof演算子 | オペランドの大きさ(バイト数) | ← |
単項演算子 | sizeof 式 | sizeof演算子 | オペランドの大きさ(バイト数) | ← |
sizeof演算子はオペランドの大きさをバイト数で返す。
//例 sizeof演算子の使用例
#include <stdio.h>
int main(void)
{
char c;
int i;
float f;
double d;
long v[100];
printf("charのサイズは%zu。\n", sizeof(char));
printf("intのサイズは%zu。\n", sizeof(int));
printf("floatのサイズは%zu。\n", sizeof(float));
printf("doubleのサイズは%zu。\n", sizeof(double));
printf("変数cのサイズは%zu。\n", sizeof c);
printf("変数iのサイズは%zu。\n", sizeof i);
printf("変数fのサイズは%zu。\n", sizeof f);
printf("変数dのサイズは%zu。\n", sizeof d);
printf("配列vのサイズは%zu。\n", sizeof *v);
printf("sizeof(sizeof 0)のサイズは%zu。\n", sizeof(sizeof(0)));
}
_Alignof演算子
編集_Alignof演算子とは、オペランドのアラインメント要件(バイト数: 型は size_t)を返す演算子です。[17]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
単項演算子 | _Alignof(型名) | _Alignof演算子 | オペランドのアラインメント要件(バイト数) | ← |
_Alignof演算子はオペランドのアラインメント要件をバイト数で返す。 _Alignof演算子のオペランドには(sizeof演算子と異なり)式を指定できません。 <stdalign.h>ヘッダファイルが標準に追加された。
//例 _Alignof演算子の使用例
#include <stdio.h>
int main(void)
{
printf("charのアラインメント要件は%zu。\n", _Alignof(char));
printf("intのアラインメント要件は%zu。\n", _Alignof(int));
printf("floatのアラインメント要件は%zu。\n", _Alignof(float));
printf("doubleのアラインメント要件は%zu。\n", _Alignof(double));
return 0;
}
実行例(環境: Intel Xeon Processor (Cascadelake) 上の FreeBSD 13.0-STABLE #0 stable/13-6e405dd9e x clang version 11.0.1/llvmorg-11.0.1-0-g43ff75f2c3fe)
charのアラインメント要件は1。 intのアラインメント要件は4。 floatのアラインメント要件は4。 doubleのアラインメント要件は8。
キャスト演算子
編集キャスト演算子とは、式の値を指定された型に型変換した値を返す演算子です。[18]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
キャスト演算子 | (データ型)式 | キャスト演算子 | 式の値を指定された型に型変換した値を返す。 | ← |
型キャストとは、式の値を指定されたデータ型に変換します(明示的な型変換)。
//例 型キャストの使用例
#include "stdio.h"
int main(void)
{
double d = 3.14;
printf("dを整数型に変換した値は%d。\n", (int)d); //浮動小数点型の変数dを整数型に変換したものを表示します。
}
ビット単位の演算子
編集各オペランドは整数型をもたなければなりません。 <<演算子の結果は、左オペランドを右オペランド分左にシフトした値です。 >>演算子の結果は、左オペランドを右オペランド分右にシフトした値です。[19]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
ビット単位のシフト演算子 | << | <<演算子 | 左オペランドを右オペランドビット分左にシフトした値。 空いたビットには0を詰めます。 |
→ |
>> | >>演算子 | 左オペランドを右オペランドビット分右にシフトした値。 | → |
- ビット単位のシフト演算子の使用例
#include <stdio.h> int main(void) { unsigned char c = 0xaa; // 0b10101010 unsigned char d = c << 1; // 0b01010100 unsigned char e = c >> 1; // 0b01010101 printf("dの値は%#x。\n", d); printf("eの値は%#x。\n", e); }
~演算子は右オペランドの各ビットを0なら1へ1なら0へ反転します。 右オペランドは整数型をもたなければなりません。 [20] 2項&演算子の結果は、オペランドのビット単位の論理積です。 つまり、対応するビットが両方ともセットされている場合ビットをセットし、それ以外の場合ビットをセットしません。 各オペランドの型は、整数型でなければなりません。 [21] ^演算子の結果は、オペランドのビット単位の排他的論理和です。 つまり、対応するビットのいずれか一方だけがセットされている場合ビットをセットし、それ以外の場合ビットをセットしません。 各オペランドの型は、整数型でなければなりません。 [22] |演算子の結果は、オペランドのビット単位の論理和です。 つまり、対応するビットの少なくとも一方がセットされている場合ビットをセットし、それ以外の場合ビットをセットしません。 各オペランドの型は、整数型でなければなりません。 [23]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
単項演算子 | ~ | ~演算子 | 右オペランドのビット単位の補数 | ← |
ビット単位のAND演算子 | & | 2項&演算子 | 両オペランドのビット単位の論理積 | → |
ビット単位の排他OR演算子 | ^ | ^演算子 | 両オペランドのビット単位の排他的論理和 | → |
ビット単位のOR演算子 | | | 演算子 | 両オペランドのビット単位の論理和 | → |
- ~演算子の使用例
#include <stdio.h> int main(void) { unsigned char c = 0xaa; // 0b10101010 unsigned char d = ~c; // 0b01010101 printf("dの値は%#x。\n", d); }
- ビット単位のAND演算子の使用例
#include <stdio.h> int main(void) { unsigned char c = 0x3; // 0b00000011 unsigned char d = 0x5; // 0b00000101 unsigned char e = c & d; // 0b00000001 printf("eの値は%#x。\n", e); }
- ビット単位の排他OR演算子の使用例
#include <stdio.h> int main(void) { unsigned char c = 0x3; // 0b00000011 unsigned char d = 0x5; // 0b00000101 unsigned char e = c ^ d; // 0b00000110 printf("eの値は%#x。\n", e); }
- ビット単位のOR演算子の使用例
#include <stdio.h> int main(void) { unsigned char c = 0x3; // 0b00000011 unsigned char d = 0x5; // 0b00000101 unsigned char e = c | d; // 0b00000111 printf("eの値は%#x。\n", e); }
条件演算子
編集条件演算子は、式1が0と比較して等しい場合式2を評価し、等しくない場合式3を評価します。 式2または式3の値を結果とします。[24]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
条件演算子 | 式1 ? 式2 : 式3 | 条件演算子 | 式1が0と比較して等しい場合式2を評価し、等しくない場合式3を評価します。 | ← |
次のようなif文は、条件演算子を用いて、次のように書き換えることができます。
// aとbの内、大きいほうをcに代入します。 if (a > b) c = a; else c = b;
↓
c = (a > b) ? a : b;
複合代入
編集形式E1 op= E2の複合代入は、 左辺値E1がただ一回だけ評価される点を除いて、 単純代入式E1 = E1 op (E2)と同じとします。[25]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
代入演算子 | *= | *=演算子 | 形式E1 op= E2の複合代入は、 左辺値E1がただ一回だけ評価される点を除いて、 単純代入式E1 = E1 op (E2)と同じとします。 | ← |
/= | /=演算子 | |||
%= | %=演算子 | |||
+ = | +=演算子 | |||
-= | -=演算子 | |||
<<= | <<=演算子 | |||
>>= | >>=演算子 | |||
&== | &=演算子 | |||
^= | ^=演算子 | |||
|= | |=演算子 |
次のような代入文は、複合代入を用いて、次のように書き換えることができます。
a = a * b; a *= b;
a = a / b; a /= b;
a = a + b; a += b;
a = a - b; a -= b;
a = a << b; a <<= b;
a = a >> b; a >>= b;
a = a & b; a &= b;
a = a ^ b; a ^= b;
a = a | b; a |= b;
コンマ演算子
編集コンマ演算子は、左オペランドをボイド式として評価し、次に右オペランドを評価しそれを結果として返す。[26]
演算子の種類 | 演算子 | 演算子の名称 | 意味 | 結合規則 |
---|---|---|---|---|
コンマ演算子 | , | コンマ演算子 | 左オペランドをボイド式として評価し、次に右オペランドを評価しそれを結果として返す。 | → |
- コンマ演算子の使用例
#include <stdio.h> int main(void) { int i = 1, j = 2, k; k = (i, j); // kにはjの値が代入されます。 printf("kの値は%d。\n", k); }
式に関する構文の抜粋
編集N2176 C17 ballot ISO/IEC 9899:2017 § Annex A (informative) Language syntax summary から、§6.5 Expressions:式に関連した部分を抜粋しました。 トークンはリンクになっています。
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5 Expressions:式[27].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.1 Primary expressions:一次式[28].
- primary-expression
- identifier
- constant
- string-literal
- ( expression )
- generic-selection
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.1.1 Generic selectionC11:総称選択[29].
- generic-selection
- _Generic ( assignment-expression , generic-assoc-list )
- generic-assoc-list
- generic-association
- generic-assoc-list , generic-association
- generic-association
- type-name : assignment-expression
- default : assignment-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.2 Postfix operators:後置演算子[14].
- postfix-expression
- primary-expression
- postfix-expression [ expression ]
- postfix-expression ( argument-expression-listopt )
- postfix-expression . identifier
- postfix-expression -> identifier
- postfix-expression ++
- postfix-expression --
- ( type-name ) { initializer-list }
- ( type-name ) { initializer-list , }
- argument-expression-list
- assignment-expression
- argument-expression-list , assignment-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.2.1 Array subscripting:配列の添字付け[30].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.2.2 Function calls:関数呼出し[31].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.2.3 Structure and union members:構造体及び共用体のメンバー[32].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.2.4 Postfix increment and decrement operators:後置増分及び後置減分演算子[33].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.2.5 Compound literals:複合リテラル[15].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.3 Unary operators:単項演算子[34].
- unary-expression
- postfix-expression
- ++ unary-expression
- -- unary-expression
- unary-operator cast-expression
- sizeof unary-expression
- sizeof ( type-name )
- _Alignof ( type-name )
- unary-operator
- & * + - ~ !
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.3.1 Prefix increment and decrement operators:前置増分及び前置減分演算子[35].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.3.2 Address and indirection operators:アドレス及び間接演算子[36].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.3.3 Unary arithmetic operators:単項算術演算子[5].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.3.4 The sizeof and _Alignof operators:sizeof演算子[37].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.4 Cast operators:キャスト演算子[38].
- cast-expression
- unary-expression
- ( type-name ) cast-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.5 Multiplicative operators:乗除演算子[4].
- multiplicative-expression
- cast-expression
- multiplicative-expression * cast-expression
- multiplicative-expression / cast-expression
- multiplicative-expression % cast-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.6 Additive operators:加減演算子[3].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.7 Bitwise shift operators:ビット単位のシフト演算子[39].
- shift-expression
- additive-expression
- shift-expression << additive-expression
- shift-expression >> additive-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.8 Relational operators:関係演算子[40].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.9 Equality operators:等価演算子[41].
- equality-expression
- relational-expression
- equality-expression == relational-expression
- equality-expression != relational-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.10 Bitwise AND operator:ビット単位のAND演算子[42].
- AND-expression
- equality-expression
- AND-expression & equality-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.11 Bitwise exclusive OR operator:ビット単位の排他OR演算子[43].
- exclusive-OR-expression
- AND-expression
- exclusive-OR-expression ^ AND-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.12 Bitwise inclusive OR operator:ビット単位のOR演算子[44].
- inclusive-OR-expression
- exclusive-OR-expression
- inclusive-OR-expression | exclusive-OR-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.13 Logical AND operator:論理AND演算子[45].
- logical-AND-expression
- inclusive-OR-expression
- logical-AND-expression && inclusive-OR-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.14 Logical OR operator:論理OR演算子[46].
- logical-OR-expression
- logical-AND-expression
- logical-OR-expression || logical-AND-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.15 Conditional operator:条件演算子[47].
- conditional-expression
- logical-OR-expression
- logical-OR-expression ? expression : conditional-expression
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.16 Assignment operators:代入演算子[48].
- assignment-expression
- conditional-expression
- unary-expression assignment-operator assignment-expression
- assignment-operator
- = *= /= %= += -= <<= >>= &= ^= |=
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.16.1 Simple assignment:単純代入[6].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.16.2 Compound assignment:複合代入[49].
- N2176 C17 ballot ISO/IEC 9899:2017 §6.5.17 Comma operator:コンマ演算子[50].
- expression
- assignment-expression
- expression , assignment-expression
脚註
編集- ^ 『ISO/IEC 9899:2011』p.39「6.3.1.8 Usual arithmetic conversions」
- ^ 『JISX3010:2003』p.33「6.3.1.8 通常の算術型変換」
- ^ 3.0 3.1 N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 66, §6.5.6 Additive operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ 4.0 4.1 N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 66, §6.5.5 Multiplicative operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ 5.0 5.1 N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 64, §6.5.3.3 Unary arithmetic operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ 6.0 6.1 N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 73, §6.5.16.1 Simple assignment. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ 『JISX3010:2003』p.62「6.5.8 関係演算子」
- ^ 『JISX3010:2003』p.63「6.5.8 等価演算子」
- ^ 『JISX3010:2003』p.58「6.5.3.3 単項算術演算子」
- ^ 『JISX3010:2003』p.65「6.5.8 論理AND演算子」
- ^ 『JISX3010:2003』p.65「6.5.8 論理OR演算子」
- ^ 『JISX3010:2003』p.54「6.5.2.4 後置増分及び後置減分演算子」
- ^ 『JISX3010:2003』p.57「6.5.3.1 前置増分及び前置減分演算子」
- ^ 14.0 14.1 N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 57, §6.5.2 Postfix operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ 15.0 15.1 15.2 15.3 15.4 15.5 15.6 N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 61, §6.5.2.5 Compound literals. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ 『JISX3010:2003』p.58「6.5.3.4 sizeof演算子」
- ^ 『ISO/IEC 9899:2011』p.64「6.5.3.4 The sizeof and _Alignof operators」
- ^ 『JISX3010:2003』p.59「6.5.4 キャスト演算子」
- ^ 『JISX3010:2003』p.62「6.5.7 ビット単位のシフト演算子」
- ^ 『JISX3010:2003』p.58「6.5.3.3 単項算術演算子」
- ^ 『JISX3010:2003』p.64「6.5.10 ビット単位のAND演算子」
- ^ 『JISX3010:2003』p.64「6.5.11 ビット単位の排他OR演算子」
- ^ 『JISX3010:2003』p.65「6.5.10 ビット単位のOR演算子」
- ^ 『JISX3010:2003』p.65「6.5.15 条件演算子」
- ^ 『JISX3010:2003』p.68「6.5.16.2 複合代入」
- ^ 『JISX3010:2003』p.68「6.5.17 コンマ演算子」
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 55, §6.5 Expressions. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 56, §6.5.1 Primary expressions. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 56, §6.5.1.1 Generic selection. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 57, §6.5.2.1 Array subscripting. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 58, §6.5.2.2 Function calls. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 59, §6.5.2.3 Structure and union members. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 60, §6.5.2.4 Postfix increment and decrement operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 63, §6.5.3 Unary operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 63, §6.5.3.1 Prefix increment and decrement operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 64, §6.5.3.2 Address and indirection operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 64, §6.5.3.4 The sizeof and _Alignof operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 65, §6.5.4 Cast operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 68, §6.5.7 Bitwise shift operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 68, §6.5.8 Relational operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 69, §6.5.9 Equality operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 70, §6.5.10 Bitwise AND operator. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 70, §6.5.11 Bitwise exclusive OR operator. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 70, §6.5.12 Bitwise inclusive OR operator. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 71, §6.5.13 Logical AND operator. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 71, §6.5.14 Logical OR operator. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 71, §6.5.15 Conditional operator. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 72, §6.5.16 Assignment operators. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 74, §6.5.16.2 Compound assignment. オリジナルの2018-12-30時点によるアーカイブ。 .
- ^ N2176 C17 ballot ISO/IEC 9899:2017. ISO/IEC JTC1/SC22/WG14. p. 75, §6.5.17 Comma operator. オリジナルの2018-12-30時点によるアーカイブ。 .
参考文献
編集- 国際標準化機構/国際電気標準会議 ISO/IEC 9899:2018(en) Information technology — Programming languages — C(2018-07-05)
- 日本工業標準調査会(当時、現:日本産業標準調査会)『JISX3010 プログラム言語C』2003年12月20日改正