4
void func() {assert(0);}
int main () {void func();}

上記のコードはfunc()を呼び出さないか、少なくともアサーションに到達しません。私が本当に知る必要があるというわけではありませんが、私はただ興味があります、ここで何が起こっているのですか?

4

4 に答える 4

10

func何も返さず、引数をとらないという名前の関数のプロトタイプを宣言しています。これは、関数呼び出しと関数プロトタイプの微妙な違いの1つです。main上記の行、、void func() {assert(0);}は、これがプロトタイプであるか呼び出しであるかに影響を与えないことに注意してください。あなたはそれを取り除くことができ、コードは同じことをするでしょう-つまり、何もしません。

これは、関数プロトタイプを再宣言できることも示しています。あなたもこれを持つことができます:

int main() {
    void blah();
    void blah();
    void blah();
    void blah();
}

そして、コードは以前と同じように動作します-何もしません。

を省略voidすると、関数が呼び出されます。

また、パラメータを受け取る関数の場合、次のことに注意してください。

int main() { func(4); }

voidこのように前に追加した場合、プロトタイプにはなりません。

int main() { void func(4); }

構文エラーが発生するだけです。

于 2011-08-04T02:23:28.513 に答える
5

他の人が指摘したように、行

void func();

inside ofmainは、関数の呼び出しではなく、関数のプロトタイプとして扱われますfunc。C および C++ では、必要に応じて関数内で関数プロトタイプを宣言できますが、実際にはめったに行われません。

これが合法であるという事実は、プログラマーにとってあらゆる種類の頭痛の種です。たとえば、コードを次のように書き直した場合

(void) func();

次に、これは、 「この戻り値は気にしない」ことを示すために戻り値funcの型が明示的にキャストされる呼び出しとしてコンパイルされます。voidつまり、この括弧のセットは、宣言をステートメントに変更します。

C++ では、以下のコードが関数のプロトタイプであり、既定のコンストラクターを呼び出す変数宣言ではないという事実によって、この問題がさらに悪化する可能性があります。

Object myObject();

けれど

Object myObject(137);

オブジェクトを作成し、コンストラクターに 137 を渡します。

Object myObject;

コンストラクターを呼び出さずにオブジェクトを作成します。

コンストラクターを呼び出しながらオブジェクトを宣言しようとすると、「最も厄介な解析」と呼ばれる言語のひどいエッジケースがあります。たとえば、次のコードは有効な C++ ですが、変数宣言ではなく関数宣言です。

set<int> mySet(istream_iterator<int>(cin), istream_iterator<int>());

istream_iterator<int>問題は、これが 2 つの一時的な をパラメーターとして受け入れるオブジェクトの作成ではなく、関数宣言として解析される可能性があることです。これを修正するには、C++ で次のように記述する必要があります。

set<int> mySet(istream_iterator<int>(cin), (istream_iterator<int>()));

上記のように、余分な括弧は、ステートメントを関数プロトタイプから宣言に強制的に曖昧さをなくします。

お役に立てれば!

于 2011-08-04T02:29:15.113 に答える
4

不要な場合でも関数を宣言できます。それがあなたがしたことであり、関数を再宣言しました。

于 2011-08-04T02:23:56.627 に答える
0

void func()内でローカル関数を宣言していますmain()。このvoidステートメントは、それが関数呼び出しではなく宣言であることをコンパイラーに示します。したがって、を削除するvoidと、関数が呼び出されます。

于 2011-08-04T04:38:53.893 に答える