2015-12-28 162 views
6

"C++プログラミング言語 - 第4版"を読んでいますが、C++構文のハングを取得するための簡単な演習を入力しました。眉。要するに、私がメインでaccept()を追加するのを忘れ:関数呼び出しが足りない引数リスト警告

bool accept() 
{ 
    cout << "Do you want to proceed (y or n)?\n"; 

    char answer = 0; 
    cin >> answer; 

    if (answer == 'y') 
    { 
     return true; 
    } 
    return false; 

} 

int main() 
{ 
    accept; 
} 

これが実行され、コンパイルおよび(VS2015で)

C4551生成 - 関数呼び出し欠落している引数リストを

私は自分自身が「」を読んでいることに気がつきました。そして、彼らは大部分が「自分のコードをデバッグする」ことを要求しているので、クローズされるはずの質問がたくさんあります。

私は、コードがコンパイルされ、実行され、関数が(ユーザー入力を待っている)ブロッキング文と戻り値の型を含んでいると、カッコが欠落していてもすべてのコードが期待通りに実行されると考えました。しかし、そうではありません。

また、私は私がしようとすると(それが実際に起こっていたことだった場合)、任意の最適化を防ぐためにbool a = accept; cout << a;に、メインにacceptへの呼び出しを変更すると考えました、それはどちらかaccept()コードを呼び出していませんでした。私が知って興味が何

は次のとおりです。

  1. acceptへの呼び出しがに何をコンパイルなっていますか? accept内のコードが呼び出さ取得されていないのはなぜ
  2. なぜこれだけ警告、およびエラーではなく(私はより多くのように、これが受け入れられるか疑問だ、私はエラーとしてそれを表示するように設定を変更することができます知っています実際の結果が期待された結果と異なる場合は、デフォルトでは「劇的に」ですか?この質問は意見に基づくものかもしれませんが、同意すれば省略してください)
  3. bool a = accept; cout << a;コードをメインで実行すると、出力として1が生成されます。 falseがデフォルトのbool値(少なくともC#の場合)で、受け入れコードが実行されないため真の値を返すものは何もありません。
+2

の可能性のある重複した[私は括弧なしで関数を使用するときに、なぜC++コンパイラは文句ないのですか?](http://stackoverflow.com/questions/11082329/why-doesnt-the-c-compiler-complain -when-i-use-functions-括弧なし)およびhttp://stackoverflow.com/questions/17073066/g-calling-function-with-parenthesis-not-f-but-f-why-always-return –

+2

@ HithamS.AlQadheeb:近づいている間に、彼は関数ポインタと 'bool'に崩壊しなければならないいくつかのことを尋ねます。だから完全な複製ではありません。 –

+1

@ HithamS.AlQadheeb "複製"の回答は私の質問の一部にしか答えません。私のコンパイラが警告を出していたので、「重複」の質問のタイトルはちょうど私が経験していたものとまったく正反対のもので、警告文を質問タイトルとして使用しています。私の同じタイトルを使用している他の質問は、「なぜ私のコードは機能しないのですか?」と質問しているので、あなたが見つけた「dupe」が(まともなものではなく)検索可能。 – Kcvin

答えて

14
  1. acceptへの呼び出し」はありません。 #3を参照してください。

  2. #1。

  3. 関数呼び出しの構文(すなわち:())のない関数名の使用は、あなたが関数自体にアクセスしていることを意味します。あなたは、例えば、(関数へのポインタ減衰経由)関数ポインタに格納することができます:あなたは、その後acceptを呼ぶだろうvar();を発行することができ

    using my_func = bool(*)(); //Function that takes nothing and returns a bool. 
    my_func var = accept; //Store a pointer to `accept`. 
    

    しかし、あなたは決して関数を格納しないので、コンパイラはおそらくを呼び出すことを意味していると推測します。関数のポインタにはアクセスしません。 accept;は合法的なC++ステートメントなので、コンパイラーはエラーにはなりません。文は何も成し遂げず、おそらく関数を呼び出すことを意図しているので、警告を出すことができます。 1;のようなステートメントと違いはありません。完全に合法ですが、まったく役に立たないものです。

  4. これはC++トリッキーなためです。 NULLでないポインタはブール値trueに減衰します。acceptは、NULLでない関数ポインタに崩壊します。したがって、boolに変換すると、trueになります。あなたはまだではない関数を呼び出しています。

8

C++では、式の後にセミコロンを付けると、法的声明です。 (なぜなら、Cはあなたにこれをさせるので、私は思う)。

5; 
3 + 5; 
1 % 2 == 0; 

このフォームの文の効果は、式が評価され、その後、廃棄されていることである:それは、次のすべての法的書類であることを意味します。これらのどれも副作用がないので、良い最適化コンパイラはここでのロジックをすべて削除するだけです。 acceptが機能acceptを基準に評価される式ですので、あなたの場合は

は、

accept; 

を書くことは法律上の声明です。つまり、accept;は「acceptのアドレスを評価し、それを破棄する」という意味です。ここで関数が呼び出されない理由は、関数名自体が関数を呼び出さないためです。実際に呼び出しを行うには、かっこ(関数呼び出し演算子)が必要です。これは、関数を別の関数に渡す場合などに便利です。これはnameOfMyComparisonFunctionを呼び出してしようとした場合の引数は、ソートルーチンまで知ることができないので、

std::sort(range.begin(), range.end(), nameOfMyComparisonFunction) 

ここで、それは、本当の問題のようになります。たとえば、あなたはこのように、std::sortに比較関数を渡したいかもしれません始めます。

これはなぜ警告であり、エラーではないのですか?まあ、それは完全に合法的なC++コードなので、コンパイラはそれを準拠してエラーと呼ぶことはできません。ただし、コンパイラは警告として警告することは間違いありません。ほとんどの場合、エラーが発生したことを意味します。つまり、ほとんどのコンパイラには警告がエラーとして報告される設定があります。警告レベルを高く設定すると、コンパイラはおそらくとなります。は「これは私があなたが何かを混乱させたと思うほど疑わしいです。あなたの最後の1については

- なぜ

bool a = accept; 

は、非NULLポインタが暗黙的にtrueに変換し、任意のNULLポインタが暗黙的にfalseに変換し、C++でtrue?aを設定終わるん。 C++では、関数は暗黙的にポインタに変換されるので、acceptaccept関数のアドレスに評価されます。これはヌルではないため、atrueに設定します。あなたはその後、

cout << a << endl; 

を書くときbool値はデフォルトで1と0のではなくtruefalseとして印刷されているため、値は、1として印刷されます。つまり、あなたは

cout << boolalpha << a << endl; 

と書くことができ、代わりにtrueと表示されます。

希望すると便利です。

関連する問題