if文(イフぶん、)は、プログラミング言語における条件分岐の構文である。プログラムの流れを制御する制御構造の一つに位置づけられる。
記述された条件式の真理値(真または偽)を判定し、その結果に応じて次に実行する処理を選択する用途で用いられる。一般的に、条件が成立した場合の「then節」と、不成立時の代替処理を定義する「else節」で構成される。複雑な判断が必要な場合は、これらを入れ子構造(ネスト)状に配置することで、多方向への分岐を実現できる点が特徴である。
真偽値 「真として(あるいは、偽として)扱うべき値」について詳説する。式の値が真理値をとるブーリアン型でなければならない言語もあるが、そのように限定していない言語もある。(C99以前の)C言語にはそもそもブーリアン型が無くで代用しているが、条件式としては汎整数型のゼロ(0)の他、ヌルポインタや浮動小数点数型の 0.0 なども偽として扱われる。Rubyではnilとfalse以外は真として扱われる。JavaScriptにはtruthyとfalsyという用語があり、falseの他いくつかの値がfalsyで、その他の多くの値はtruthyである。比較的少数の偽になる値の他は、真、という言語が多いが、それと逆に、Dart言語(のproduction mode)のようにtrue以外は偽という言語もある(checked modeではbool以外の型だとエラー)。
構文など 以下ではいくつかの言語やソフトウェアにおける、if文またはそれに類似したものの構文(syntax)などについて述べる。 C if文の条件式はスカラー型の式である(構造体や共用体のような複合型の式は使えない)ISO/IEC 9899:1999 §6.8.4.1 The if statement。C99よりも前の規格では真理値のみを扱うための型は無かったため、従来から型で代用されてきた。整数値0に等しい値(あるいは暗黙変換によって0に等しくなる値)は偽、他の値は真として扱われる。真を代表して表すための値は整数値1である(比較式の結果は型であり、0または1となることが保証されている比較演算子 - cppreference.com (C))。then節とelse節には、1個の文か、{ }で囲まれる複文(ブロック)を書く。
真の時だけ実行するとき if (条件式) then節 真と偽の両方に振り分けるとき if (条件式) then節 else else節
複数の条件で分岐するときは以下のように書くことができる。 int x = f(); if (x == 1) { /* x の値が 1 のとき */ } else if (x == 2) { /* x の値が 2 のとき */ } else { /* x の値が 1 でもなく 2 でもないとき */ }
実際には以下のようにif-elseの入れ子となっているだけである。 int x = f(); if (x == 1) { /* x の値が 1 のとき */ } else if (x == 2) { /* x の値が 2 のとき */
else { /* x の値が 1 でもなく 2 でもないとき */
上記のコードはswitch文で書くこともできるが、比較対象が整数定数でない場合や、1つの条件式にAND条件やOR条件を組み合わせる場合はif文を使う必要がある。ただしあまりに多数の条件分岐をif-elseで記述すると、入れ子階層の上限に達してしまい、コンパイル不能となることもあるFatal Error C1061 | Microsoft Learn。C99の規格で保証されている入れ子階層の数は127までであるISO/IEC 9899:1999 §5.2.4.1 Translation limits。多数のcaseラベルを含むswitch文はコンパイラによってテーブルジャンプに置き換えられることもあり、その最適化が施された場合は最初のラベルに該当するケースと最後のラベルに該当するケースでパフォーマンスに差はない。一方、if文における最後の分岐に該当する場合、それ以前の分岐における条件式をすべて実行することになり、分岐の数に応じてパフォーマンスが悪化する。
Cでは代入は文ではなく式であり値を返すため、以下のように条件式として代入式を使うこともできる。 int x; if (x = f()) { /* x の値が 0 でないとき */ } else { /* x の値が 0 のとき */ } しかし不注意なプログラマは比較演算子の==と間違えて=と記述してしまうこともあるため、このような書き方をすると警告を出す仕様になっているコンパイラも多いCompiler Warning (level 4) C4706 | Microsoft LearnDiagnostic flags in Clang — Clang git documentation。
C++ C++はCから発展した言語であり、構文なども概ね上位互換だが、細かな仕様において互換性のない部分も多い。
値として (0) または (1) のみを取りうる型を持っており、組み込みの型に対する比較式の結果は型となる比較演算子 - cppreference.com (C++)。if文の条件式はこの型に暗黙的に変換可能な式を受け付ける。Cとの互換性のため、型は整数型の一種であり、その他の整数型や浮動小数点数型、ポインタ型などの値は、条件式の文脈において型に暗黙変換可能となっている。そのため、このような型Tへの暗黙変換演算子オーバーロードを持つユーザー定義型のインスタンスであれば、if文の条件式として直接使うことも可能である。
struct MyStruct { std::string name; operator size_t() const { return name.size(); }
MyStruct obj = {"abc"}; if (obj) { // obj.name が空文字列でないとき。 } size_t size = obj; // 暗黙の型変換があらゆる場面で発動する。
ただしこのような暗黙変換は思わぬ場面で発動することもあり、問題を引き起こすことが多い。安全のため、C++11では、明示的な型変換演算子オーバーロードを定義できるの構文がサポートされた明示的な型変換演算子のオーバーロード - cpprefjp C++日本語リファレンス。Tがの場合、条件式の文脈においては暗黙変換可能となる。
struct MyStruct { std::string name; explicit operator bool() const { return !name.empty(); }
MyStruct obj = {"abc"}; if (obj) { // obj.name が空文字列でないとき。 } bool b = static_cast<bool>(obj); // 条件式の文脈でない場合、型変換には明示的なキャストが必要。
C++ではif文の条件式で変数を宣言することも可能である。変数の生存期間はそのif-else文を抜けるまでとなる。 if (int x = f()) { // x の値が 0 でないとき。 } else { // x の値が 0 のとき。 }
C++17では、if文における初期化と条件式を分離した構文が使えるようになったif文とswitch文の条件式と初期化を分離 - cpprefjp C++日本語リファレンス。 if (int x = f(); x == 123) { // x の値が 123 のとき。 } else { // x の値が 123 でないとき。 }
Java Javaのif文は条件式として型のみを許可する。型の変数への代入またはプリミティブラッパークラス型の変数への代入を除き、代入式を記述することはできない。
C++のようにif文の条件式の中で変数を宣言することはできないが、Java 16では、演算子を使ったパターンマッチングの構文をサポートするようになったJava言語更新 - instanceofのパターン・マッチング | Java SE 16。 Object obj = getSomeObject(); if (obj instanceof String str) { // obj の型が String のとき。 System.out.println("String length = " + str.length()); } else { // obj の型が String でないとき。 } 上記は下記と等価である。 Object obj = getSomeObject(); if (obj instanceof String) { // obj の型が String のとき。 String str = (String) obj; System.out.println("String length = " + str.length()); } else { // obj の型が String でないとき。 }
C# C#はJavaとよく似ており、if文は条件式として型のみを許可する。型の変数への代入またはへの暗黙変換演算子などをユーザー定義した型の変数への代入を除き、代入式を記述することはできない。
C# 7では演算子が拡張され、型パターンなどの構文が使えるようになったDissecting the pattern matching in C# 7 - Developer Support第3回 型による分岐の改良:特集:C# 7の新機能詳説(2/2 ページ) - @IT。 object obj = GetSomeObject(); if (obj is string str) { // obj の型が string のとき。 System.Console.WriteLine("String length = " + str.Length); } else { // obj の型が string でないとき。 } // 変数 str は if-else 文を抜けた後も使用できるが、未割り当て(未初期化)となる。
Lisp Lispでは、ifは関数のような見掛けだが実引数が評価されない特殊形式である(cond特殊形式に置換されるマクロのこともある)。真偽値は、nil という名前や中身の無いカッコ () で表現される空リストが偽として扱われ、他の値は真として扱われる。then節とelse節のどちらも式である。
真の時だけ実行するとき (if 条件式 then節) 真と偽の両方に振り分けるとき (if 条件式 then節 else節)
Lispにはcondという、同等の機能を実現できる特殊形式もある。仕様や実装によっては、ifがcondに展開されるマクロのこともあるし、condがifに展開されるマクロのこともある。
Pascal then節とelse節には、1個の文か、begin - end で囲まれる複文を書く。
真の時だけ実行するとき if 条件式 then then節 真と偽の両方に振り分けるとき if 条件式 then then節 else else節
Ada Adaでは条件式の型はBoolean(もしくはBooleanの派生型)でなければならない。これはJava等も同様である。
真の時だけ実行するとき if 条件式 then then節 end if; 真と偽で実行文を変えるとき if 条件式 then then節 else else節 end if;
Perlの場合 真の時だけ実行するとき 真文 if 条件文 偽の時だけ実行するとき 偽文 unless 条件文 また、C言語風の記述法も可能である。
真の時だけ実行するとき if(条件文) { 真文 } 真と偽で実行文を変えるとき if(条件文) { 真文 } else { 偽文 }
Rubyの場合 Rubyのifは厳密に言えばif式であり、条件が成立した方の節で最後に評価された式の値を返す。
真の時だけ実行するとき if 条件式 (then) 真文 end
真と偽で実行文を変えるとき if 条件文 (then) 真文 else 偽文 end
BASICの場合 真の時だけ実行するとき IF 条件式 THEN 真文
真と偽で実行文を変えるとき IF 条件式 THEN 真文 ELSE 偽文
真文・偽文が1行で書ききれない場合はgoto文が併用される。
Visual Basicの場合 Visual Basic (VB)、Visual Basic for Applications (VBA)、Visual Basic .NET (VB.NET) は複文にも対応している。
真の時だけ実行するとき If 条件式 Then 真文 End If
真と偽で実行文を変えるとき If 条件式 Then 真文 Else 偽文 End If
真文・偽文が1行だけの場合にはBASICと同様の書き方(単一行構文)も可能であるUsing If...Then...Else statements (VBA) | Microsoft LearnIf...Then...Else ステートメント - Visual Basic | Microsoft Learn。
表計算ソフトウェア 表計算ソフトウェアのMicrosoft Excel、OpenOffice.org Calc、LibreOffice Calc、Google スプレッドシートなどでは、ワークシート関数のひとつとしてIF関数をサポートしている。
Excelの場合は以下の構文であるIF 関数 - Microsoft サポート。
IF(テストする条件, 真の場合の値, 偽の場合の値)
関数という性質上、「偽の場合は何も返さない(何も実行しない)」というようなことはできないが、偽の場合は0や空文字列""を返すといった形で記述できる。
LibreOffice Calcの場合は以下の構文であるLogical Functions | LibreOffice Help。
IF(テストする条件; 真の場合の値; 偽の場合の値)
真の場合の値や偽の場合の値を空にした場合、0とみなされる。
Googleスプレッドシートの場合は以下の構文であるIF - Google ドキュメント エディタ ヘルプ。
IF(テストする条件, 真の場合の値, 偽の場合の値)
偽の場合の値(FALSE値)を省略することができ、デフォルトは空欄(ブランク)となる。
IFS関数 LibreOffice Calc 5.2以降IFS function | LibreOffice HelpおよびExcel 2019以降(Office 365含む)IFS 関数 - Microsoft サポートではIFS関数をサポートする。
IFS(条件式1, 真の場合1, 条件式2, 真の場合2, ..., 条件式127, 真の場合127)
条件式は先に評価されるべきものから並べる必要がある。IF関数の入れ子構造と処理は同一であるが、簡潔に記述できる。
LibreOffice CalcとExcelのIFS関数では、最大127個の条件をテストすることができる。ただし、IFまたはIFSであまりにも多くの条件をネストすることは推奨されていない。複数の条件は正確な順序で入力する必要があり、かつ、構築、テスト、更新を行うのが大変難しくなる場合があるからである。
IFS関数はGoogleスプレッドシートでもサポートされているIFS - Google ドキュメント エディタ ヘルプ。
FORTRAN 以下は、Fortran77以降の、論理IF文の場合である。1行のみの場合 if(条件式) 真文
複数行にまたがる場合
if(条件式1) then 条件式1が真の場合ここから ここまでのプログラムが実行される(複数行) else if(条件式2) then 条件式2が真の場合ただしすでに条件式1が成り立っている場合は除くここから ここまでのプログラムが実行される(複数行) else すべてのなかのいずれの条件にも当てはまらない場合ここから ここまでのプログラムが実行される(複数行) end if
Forthの場合 真の時だけ実行するとき 条件式 IF 真文 THEN
偽の時だけ実行するとき 条件式 NIF 偽文 THEN
真と偽で実行文を変えるとき 条件式 IF 真文 ELSE 偽文 THEN
または 条件式 NIF 偽文 ELSE 真文 THEN
ひまわりの場合 真の時だけ実行するとき もし、{条件式}ならば、( {処理} )
真と偽で実行文を変えるとき もし、{条件式}ならば、( {処理} ) 違ったら、( {処理} )
HSPの場合 真の時だけ実行するとき if 条件式 : 真文
真と偽で実行文を変えるとき if 条件式 : 真文 : else : 偽文
また、Cのようにブレイスを用いることもできる。 if 条件式 { 真文 } else { 偽文
プログラム例 特に断りがない場合naとnbの大きい方をncに代入という意味である。
Cでの例 if (na > nb) { nc = na; } else { nc = nb; } nc = (na > nb) ? na : nb としても同じ事ができる。
Common Lisp での例 (if (> na nb) (setq nc na) (setq nc nb)) Common Lispでは文ではなく式であるため、 (setq nc (if (> na nb) na nb)) と書くこともできる。
Pascalでの例 if na > nb then nc := na else nc := nb
R言語での例
FORTRANの例 if(a.eq.b) c=5
上記の記述ではa=bの場合c=5になる簡単なプログラム例である。
if(a.eq.100) then b=30 else if(a.eq.80) then b=25 else b=20 end if
上記の記述ではa=100の場合はb=30となり,a=80の場合はb=25,その他の場合はb=20となるプログラム例である。
論理積・論理和による擬似的なIf文
仮に && を論理積を表す演算子として、
左辺 && 右辺
という論理式で、左辺が真にならなければ右辺を評価しない言語(短絡評価)では、これを
If (左辺) { 右辺 }
と等価とみなすことができる。つまり左辺が条件文で、右辺が真文となるわけである。
同様に || を論理和を表す演算子だとすると、
左辺 || 右辺
は
If (Not 左辺) { 右辺 }
と等価となり、左辺が偽のときだけ右辺が実行される。
たとえばDOSやWindowsのバッチファイルでは条件付き処理シンボル&&と||があるCommand shell overview | Microsoft Learn。 CHDIR C:\HOGE || ECHO フォルダがみつかりません (もしCHDIRコマンドが失敗したら、ECHOコマンドが実行される)
JavaScriptなど言語によっては、このように論理積演算や論理和演算を擬似的なIf文にできることがある。
脚注
関連項目 論理包含 分岐命令 - 機械語 制御構造 ヨーダ記法 - If文内の条件式で定数を左辺に置くプログラミングスタイル