2013-08-03 8 views
5

と楽しい:C++プログラミング謎、次のコードスニペットを考えると関数ポインタ

#include <string> 
#include <iostream> 

int main() 
{ 
    std::string prefix("->"), middle(), suffix("<-"); 
    std::cout << "Test: " << prefix << middle << suffix << std::endl; 

    return 0; 
} 

高度なC++プログラマはなく、ただちにそれは関数宣言だ、middle()std::stringのデフォルトのctorを呼び出していないことがわかります。

はしかし興味深い情報:Visual Studioののリンカエラーとは対照的に

Test: ->1<- 

:なぜgccは、次の出力を生成しますか?誰がここで何が起こっているのか知っていますか? coutで使用する場合

+0

私はdownvoteとこの質問(トピック以外)の緊急の要求を持っている、誰かが多分私に理由を教えてくれますか?そのような質問は本当にSOの話題ですか? –

答えて

7

関数ポインタは、boolに変換されます。

なぜ関数ポインタが暗黙的にvoid *に変換されないのですか?どの演算子が< <で過負荷になっていますか?なぜなら、関数ポインタはオブジェクトポインタではないからです。

C++ 11§4.10/ 2:

Tは、CVボイドへのポインタ」型のprvalueに変換することができるオブジェクト・タイプである「CV Tへのポインタ」型のprvalue " 「cv Tへのポインタ」を「cv voidへのポインタ」に変換した結果は、オブジェクトがT型の最も派生したオブジェクト(1.8)であるかのように、T型のオブジェクトが存在する格納場所の開始点を指す(つまり、基本クラスのサブオブジェクトではありません)。 NULLポインター値は、宛先タイプのヌルポインター値に変換されます。

+2

ありがとう、私はそのような何かを推測していた。 VSが代わりにリンカーエラーを生成する理由を偶然知っていますか?どちらの行動が「標準」で、どちらが「間違っていますか? –

+4

@ D.R:あなたのプログラムは未定義の動作をしていると思うので、どちらも「正しい」と思います。 「すべてのプログラムには、そのプログラムで使用されているすべての非インライン関数または変数の定義が1つ含まれていなければなりません。**診断不要**」。 –

+0

これはどうですか? http://stackoverflow.com/questions/2064692/how-to-print-function-pointers-with-cout –

1

Yuが言ったように、関数ポインタはboolに変換されています。関数アドレスが関数のアドレスを提供するためにリンカーを必要とする、nullである場合、Visual C++、実際にテストするためのコードを生成しながら

グラム++オプティマイザは、明らかに事前評価する変換です。

ルールは

は、すべてのプログラムがそのプログラムにODR-使用されているすべての非インライン関数や変数の正確に一つの定義を含まなければならないということです。診断は必要ありません。

は、アドレスを使用しているため、 odr-usedです。定義を提供しないことにより、あなたはこのルールに違反しています。また、Standardは診断を必要としません。つまり、ツールチェーンは自由に何かをすることができます。それが必須ではありませんが、

のVisual C++は、診断を生成しています。

g ++は実際の関数の関数ポインタからヌル関数ポインタを生成できないことを知っているので、実際の変換結果はboolです。

しかし、標準ツールチェインがかここで行うことはできませんができるか言っていないため、ハードドライブをフォーマットすると、同様に有効になります。

関連する問題