If文

**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文の条件式はスカラー型の式である（構造体や共用体のような複合型の式は使えない）。C99よりも前の規格では真理値のみを扱うための型は無かったため、従来から型で代用されてきた。整数値0に等しい値（あるいは暗黙変換によって0に等しくなる値）は偽、他の値は真として扱われる。真を代表して表すための値は整数値1である（比較式の結果は型であり、0または1となることが保証されている）。then節とelse節には、1個の文か、`{ }`で囲まれる複文（ブロック）を書く。

真の時だけ実行するとき

```c
if (条件式)
 then節
```

真と偽の両方に振り分けるとき

```c
if (条件式)
 then節
else
 else節
```


複数の条件で分岐するときは以下のように書くことができる。

```c
int x = f();
if (x == 1) {
    /* x の値が 1 のとき */
}
else if (x == 2) {
    /* x の値が 2 のとき */
}
else {
    /* x の値が 1 でもなく 2 でもないとき */
}
```


実際には以下のようにif-elseの入れ子となっているだけである。

```c
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で記述すると、入れ子階層の上限に達してしまい、コンパイル不能となることもある。C99の規格で保証されている入れ子階層の数は127までである。多数のcaseラベルを含むswitch文はコンパイラによってテーブルジャンプに置き換えられることもあり、その最適化が施された場合は最初のラベルに該当するケースと最後のラベルに該当するケースでパフォーマンスに差はない。一方、if文における最後の分岐に該当する場合、それ以前の分岐における条件式をすべて実行することになり、分岐の数に応じてパフォーマンスが悪化する。

Cでは代入は文ではなく式であり値を返すため、以下のように条件式として代入式を使うこともできる。

```c
int x;
if (x = f()) {
    /* x の値が 0 でないとき */
}
else {
    /* x の値が 0 のとき */
}
```

しかし不注意なプログラマは比較演算子の`==`と間違えて`=`と記述してしまうこともあるため、このような書き方をすると警告を出す仕様になっているコンパイラも多い。

### C++
C++はCから発展した言語であり、構文なども概ね上位互換だが、細かな仕様において互換性のない部分も多い。

値として (0) または (1) のみを取りうる型を持っており、組み込みの型に対する比較式の結果は型となる。if文の条件式はこの型に暗黙的に変換可能な式を受け付ける。Cとの互換性のため、型は整数型の一種であり、その他の整数型や浮動小数点数型、ポインタ型などの値は、条件式の文脈において型に暗黙変換可能となっている。そのため、このような型`T`への暗黙変換演算子オーバーロードを持つユーザー定義型のインスタンスであれば、if文の条件式として直接使うことも可能である。


```c++
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では、明示的な型変換演算子オーバーロードを定義できるの構文がサポートされた。`T`がの場合、条件式の文脈においては暗黙変換可能となる。


```c++
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文を抜けるまでとなる。

```c++
if (int x = f()) {
    // x の値が 0 でないとき。
}
else {
    // x の値が 0 のとき。
}
```


C++17では、if文における初期化と条件式を分離した構文が使えるようになった。

```c++
if (int x = f(); x == 123) {
    // x の値が 123 のとき。
}
else {
    // x の値が 123 でないとき。
}
```


### Java
Javaのif文は条件式として型のみを許可する。型の変数への代入またはプリミティブラッパークラス型の変数への代入を除き、代入式を記述することはできない。

C++のようにif文の条件式の中で変数を宣言することはできないが、Java 16では、演算子を使ったパターンマッチングの構文をサポートするようになった。

```java
Object obj = getSomeObject();
if (obj instanceof String str) {
    // obj の型が String のとき。
    System.out.println("String length = " + str.length());
}
else {
    // obj の型が String でないとき。
}
```

上記は下記と等価である。

```java
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では演算子が拡張され、型パターンなどの構文が使えるようになった。

```cs
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節のどちらも式である。

真の時だけ実行するとき

```lisp
(if 条件式 then節)
```

真と偽の両方に振り分けるとき

```lisp
(if 条件式 then節 else節)
```


Lispにはcondという、同等の機能を実現できる特殊形式もある。仕様や実装によっては、ifがcondに展開されるマクロのこともあるし、condがifに展開されるマクロのこともある。

### Pascal
then節とelse節には、1個の文か、`begin` - `end` で囲まれる複文を書く。

真の時だけ実行するとき

```pascal
if 条件式 then
 then節
```

真と偽の両方に振り分けるとき

```pascal
if 条件式 then
 then節
else
 else節
```


### Ada
Adaでは条件式の型は`Boolean`（もしくは`Boolean`の派生型）でなければならない。これはJava等も同様である。

真の時だけ実行するとき

```ada
if 条件式 then
 then節
end if;
```

真と偽で実行文を変えるとき

```ada
if 条件式 then
 then節
else
 else節
end if;
```


### Perlの場合
真の時だけ実行するとき

```perl
真文 if 条件文
```

偽の時だけ実行するとき

```perl
偽文 unless 条件文
```

また、C言語風の記述法も可能である。

真の時だけ実行するとき

```perl
if(条件文) {
 真文
}
```

真と偽で実行文を変えるとき

```perl
if(条件文) {
 真文
} else {
 偽文
}
```


### Rubyの場合
Rubyのifは厳密に言えば**if式**であり、条件が成立した方の節で最後に評価された式の値を返す。

真の時だけ実行するとき

```ruby
if 条件式 (then)
 真文
end
```


真と偽で実行文を変えるとき

```ruby
if 条件文 (then)
 真文
else
 偽文
end
```


### BASICの場合
真の時だけ実行するとき

```basic
IF 条件式 THEN 真文
```


真と偽で実行文を変えるとき

```basic
IF 条件式 THEN 真文 ELSE 偽文
```


真文・偽文が1行で書ききれない場合はgoto文が併用される。

### Visual Basicの場合
Visual Basic (VB)、Visual Basic for Applications (VBA)、Visual Basic .NET (VB.NET) は複文にも対応している。

真の時だけ実行するとき

```vb
If 条件式 Then
 真文
End If
```


真と偽で実行文を変えるとき

```vb
If 条件式 Then
 真文
Else
 偽文
End If
```


真文・偽文が1行だけの場合にはBASICと同様の書き方（単一行構文）も可能である。

### 表計算ソフトウェア
表計算ソフトウェアのMicrosoft Excel、OpenOffice.org Calc、LibreOffice Calc、Google スプレッドシートなどでは、ワークシート関数のひとつとして`IF`関数をサポートしている。

Excelの場合は以下の構文である。

 IF(テストする条件, 真の場合の値, 偽の場合の値)

関数という性質上、「偽の場合は何も返さない（何も実行しない）」というようなことはできないが、偽の場合は`0`や空文字列`""`を返すといった形で記述できる。

LibreOffice Calcの場合は以下の構文である。

 IF(テストする条件; 真の場合の値; 偽の場合の値)

真の場合の値や偽の場合の値を空にした場合、0とみなされる。

Googleスプレッドシートの場合は以下の構文である。

 IF(テストする条件, 真の場合の値, 偽の場合の値)

偽の場合の値（`FALSE`値）を省略することができ、デフォルトは空欄（ブランク）となる。

#### IFS関数
LibreOffice Calc 5.2以降およびExcel 2019以降（Office 365含む）では`IFS`関数をサポートする。

 IFS(条件式1, 真の場合1, 条件式2, 真の場合2, ..., 条件式127, 真の場合127)

条件式は先に評価されるべきものから並べる必要がある。IF関数の入れ子構造と処理は同一であるが、簡潔に記述できる。

LibreOffice CalcとExcelの`IFS`関数では、最大127個の条件をテストすることができる。ただし、`IF`または`IFS`であまりにも多くの条件をネストすることは推奨されていない。複数の条件は正確な順序で入力する必要があり、かつ、構築、テスト、更新を行うのが大変難しくなる場合があるからである。

`IFS`関数はGoogleスプレッドシートでもサポートされている。

### FORTRAN
以下は、Fortran77以降の、論理IF文の場合である。1行のみの場合

```fortran
if(条件式) 真文
```


複数行にまたがる場合


```fortran
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での例

```c
if (na > nb) {
  nc = na;
} else {
  nc = nb;
}
```

* `nc = (na > nb) ? na : nb` としても同じ事ができる。

### Common Lisp での例

```lisp
(if (> na nb)
    (setq nc na)
    (setq nc nb))
```

Common Lispでは文ではなく式であるため、

```lisp
(setq nc (if (> na nb) na nb))
```

と書くこともできる。

### Pascalでの例

```pascal
if na > nb then nc := na else nc := nb
```


### R言語での例

### FORTRANの例

```fortran
if(a.eq.b) c=5
```


上記の記述では`a=b`の場合`c=5`になる簡単なプログラム例である。


```fortran
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のバッチファイルでは条件付き処理シンボル`&&`と`||`がある。

```bat
CHDIR C:\HOGE || ECHO フォルダがみつかりません
```

（もしCHDIRコマンドが失敗したら、ECHOコマンドが実行される）

JavaScriptなど言語によっては、このように論理積演算や論理和演算を擬似的なIf文にできることがある。

## 脚注

## 関連項目
* 論理包含
* 分岐命令 - 機械語
* 制御構造
* ヨーダ記法 - If文内の条件式で定数を左辺に置くプログラミングスタイル