条件式のタイプ
2389 ワード
に質問
次のプログラムの出力は何ですか?
残念ながら、g++ではコンパイルは通過しませんでした:
$> g++ conditional_exp.cpp conditional_exp.cpp: In function ‘int main()’: conditional_exp.cpp:10:エラー:リロードを呼び出す「f(int)」に曖昧なconditional_exp.cpp:5:注記:代替:void f(long int)conditional_exp.cpp:6:注記:void f(const char*)
条件式(1?0:1)のタイプは何ですか?
以上の出力文字iは、式のタイプを表すintである
f(1)を呼び出すと、一番上のプログラムのコンパイルは正常で、出力はlongです.
f(0)を呼び出すと,最上位のプログラムも同様のコンパイルエラーを報告する,すなわち,コンパイラから見れば(1?0:1)は0と区別されない.
字面値0のタイプはintであり、パラメータがintの関数がなく、暗黙的なタイプ変換が必要であり、0はlongに変換してもよいし、空のポインタとしてconst char*に変換してもよいし、二義性を生じ、コンパイルエラーを発生する.
次のように呼び出します.
コンパイル時と実行時の結果がこのように異なるのは、実行するルールが少し異なるのではないでしょうか.
結果から見ると、コンパイルはより厳格な検査を実行し、エラーを報告するのはcoderに注意することであり、この場所ではエラーが発生する可能性が高い.実行時には、intを暗黙的にlongに変換し、正しい関数を呼び出すルールに従います.
以下に、いくつかの試みのまとめを示します.
関数の再ロードを1つ追加すると、次のようになります.
compile errorとeclipse complainはありません.タイプはintの0で、正確な関数プロトタイプが見つかりました.タイプ変換は必要ありません.
推奨
呼び出し時に、0にL接尾辞を付けます.次のようにします.
より良い方法は、intのパラメータを追加する関数の再ロードです.
次のプログラムの出力は何ですか?
#include
using namespace std;
void f(long);
void f(const char*);
int main()
{
f(1?0:1);
return 0;
}
void f(long)
{
cout << "long" << endl;
}
void f(const char*)
{
cout << "const char*" << endl;
}
残念ながら、g++ではコンパイルは通過しませんでした:
$> g++ conditional_exp.cpp conditional_exp.cpp: In function ‘int main()’: conditional_exp.cpp:10:エラー:リロードを呼び出す「f(int)」に曖昧なconditional_exp.cpp:5:注記:代替:void f(long int)conditional_exp.cpp:6:注記:void f(const char*)
条件式(1?0:1)のタイプは何ですか?
cout << typeid(1?0:1).name() << endl;
以上の出力文字iは、式のタイプを表すintである
f(1)を呼び出すと、一番上のプログラムのコンパイルは正常で、出力はlongです.
f(0)を呼び出すと,最上位のプログラムも同様のコンパイルエラーを報告する,すなわち,コンパイラから見れば(1?0:1)は0と区別されない.
字面値0のタイプはintであり、パラメータがintの関数がなく、暗黙的なタイプ変換が必要であり、0はlongに変換してもよいし、空のポインタとしてconst char*に変換してもよいし、二義性を生じ、コンパイルエラーを発生する.
次のように呼び出します.
const char* p = NULL;
f(p==NULL?0:1);
eclipseは引き続き二義性を提示しますが、コンパイルはエラーも警告もなく、プログラム出力はlongです(なぜ1?0:1の結果はコンパイルエラーですが、ここでコンパイルは正常ですか?)コンパイル時と実行時の結果がこのように異なるのは、実行するルールが少し異なるのではないでしょうか.
結果から見ると、コンパイルはより厳格な検査を実行し、エラーを報告するのはcoderに注意することであり、この場所ではエラーが発生する可能性が高い.実行時には、intを暗黙的にlongに変換し、正しい関数を呼び出すルールに従います.
以下に、いくつかの試みのまとめを示します.
f(1?0:1); //compile error
f(0); //compile error
f(1?2:1); //call f(long)
const char* p = NULL;
f(p==NULL?0:1); //eclipse complain, compile succeed, call f(long)
f(NULL); //compile error
f(0L); //call f(long)
f((const char*)0); //call f(const char*)
関数の再ロードを1つ追加すると、次のようになります.
void f(int)
{
cout << "int" << endl;
}
compile errorとeclipse complainはありません.タイプはintの0で、正確な関数プロトタイプが見つかりました.タイプ変換は必要ありません.
f(1?0:1); //call f(int)
f(0); //call f(int)
f(1?2:1); //call f(int)
const char* p = NULL;
f(p==NULL?0:1); //call f(int)
f(NULL); //call f(long)
f(0L); //call f(long)
f((const char*)0); //call f(const char*)
推奨
呼び出し時に、0にL接尾辞を付けます.次のようにします.
f(1?0L:1);
より良い方法は、intのパラメータを追加する関数の再ロードです.
void f(int i)
{
f((long)i);
}