未規定動作

ウィキペディアから

コンピュータプログラミングにおいて、未規定動作(みきていどうさ、unspecified behavior)とは、プログラム言語の仕様が動作結果を規定せず、言語の処理系によって異なる可能性のある動作のことである。同じソースコードを異なるコンパイラでコンパイルした場合、あるいは同じコンパイラでも異なる設定でコンパイルした場合などに異なる動作を示す実行ファイルが生成される可能性がある場合、プログラムが未規定動作を含むという。言語の仕様や標準において、想定される動作の範囲が規定されている場合もあるが、実際の動作が言語の処理系に依存し、プログラムのコードだけでは完全に決定できない場合がある[1]。未規定動作は、多くの場合外部から見えるプログラムの動作には影響しないが、場合によっては結果が異なる可能性もあり、それが移植性の問題につながることもある。

定義

コンパイラがターゲットのプラットフォームに最適なコードを生成できるようにするために、プログラミング言語の標準仕様では、所与のソースコードの構造に対する動作が必ずしも規定されているわけではない[2]。全てのあり得るプログラムに対する正確な動作を明示的に規定することは不可能であり、それを規定していないことは、言語仕様のエラーや弱点とはみなされない[1]CC++では、このような移植性のない構造は、「処理系定義動作」「未規定動作」「未定義動作」の3つのカテゴリに分類される[3]

未規定動作の正確な定義は、言語によって様々である。C++では、「適格なプログラム構成や正しいデータに対する、処理系に依存する動作」と定義されている[4]。C++の標準では、可能な動作の範囲が通常提供されることにも言及している[4]。処理系定義動作とは異なり、処理系において未規定動作の動作を文書化する必要はない[4]。Cの標準では、未規定動作は「標準が2つ以上の可能性を提供し、インスタンスがどれを選択するかについてそれ以上の要件を課さない動作」と定義している[5]

未規定動作は未定義動作(undefined behavior)とは異なる。一般的に後者は、誤ったプログラム構成やデータによってもたらされるものであり、そのコンパイルや実行には何の要件も課されない[6]

処理系定義動作

CとC++では未規定動作と処理系定義動作(implementation-defined behavior)を区別している。処理系定義動作に対しては、処理系は特定の動作を選択し、それを文書化しなければならない。例えば整数型のサイズは処理系定義動作である。選択した動作は、プログラムの実行において文書化された動作と一致していなければならない。

部分式の評価順序

多くのプログラミング言語において、完全の部分式の評価順序は規定されていない。これを規定していないことにより、並列性を利用するなど、特定のプラットフォームに最適な実装が可能になる。1つまたは複数の部分式に副作用がある場合、部分式の評価順序によって完全式の評価結果が異なる可能性がある[1]。例えば、

a = f(b) + g(b);

というプログラムにおいて、fgの両方ともがbを変更する場合、f(b)g(b)のどちらが先に評価されるかによって、aに格納される結果が変わる可能性がある[1]。CとC++では、これは関数の引数にも適用される。以下に例を示す[2]

#include <iostream>
int f() {
  std::cout << "In f\n";
  return 3;
}

int g() {
  std::cout << "In g\n";
  return 4;
}

int sum(int i, int j) {
  return i + j;
}

int main() {
  return sum(f(), g()); 
}

このプログラムは標準出力に2行の文字列を出力するが、f()g()の評価順序によって表示される順番が異なる[2]Javaなどの他の言語には、オペランドや関数の引数の評価順序が明示的に定義されているものがある[7]

脚注

関連項目

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.