2013-06-12 6 views
11

C++(GNU GCC g ++)では、私のコードは()を使わない関数を "呼び出し"ています。 この関数は機能していませんが、コンパイルは正常です。g ++かっこなしの関数を呼び出す(f()ではなくf;)。なぜそれは常に1を返しますか?

さらに驚くべきことに、コードは常に何らかの説明があり1 ...

を返しますか?

私は、関数名は、普通のポインタであることが期待が、それは少し違うようだ...

は、私はすべての1の唯一のチャンスで取得しましたか?

#include <iostream> 
using namespace std; 

void pr() 
{ 
    cout << "sth"; 
} 

int main() 
{ 

pr; 
cout << pr; // output: 1 
cout << *pr; // output: 1 
cout << &pr; // output: 1 

} 
+11

関数アドレスのboolへの暗黙のキャスト。 –

+1

この投稿は役に立つかもしれません:http://stackoverflow.com/questions/2064692/how-to-print-function-pointers-with-cout – taocp

+1

暗黙の**変換**関数アドレスのboolへの変換。暗黙のキャストのようなものはありません。 –

答えて

13

あなたが実際にあなたがcoutに関数ポインタを渡している、あなたのコードでprを呼び出していません。 coutに渡されるとき、prboolに変換されます。 cout << boolalphaを事前に入力すると、1の代わりにtrueが出力されます。

EDIT:
次の過負荷を書くことができます11 C++で:(func_ptr=<address of pr>)(num_args=0)を印刷しますコールcout << prを意味

template <class RType, class ... ArgTypes> 
    std::ostream & operator<<(std::ostream & s, RType(*func)(ArgTypes...)) 
    { 
     return s << "(func_ptr=" << (void*)func << ")(num_args=" 
       << sizeof...(ArgTypes) << ")"; 
    } 

。関数自体は、あなたが明らかにしたいことを何でもすることができます。これは、C++ 11のバリデーショナルテンプレートでは、任意のアリティの関数ポインタをマッチさせることができることを示すことです。これは、オーバーロードされた関数や関数テンプレートでは、(通常はキャストを介して)どのオーバーロードを指定しなくても機能しません。

+0

これは型保証されたC++のiostreamsの誤りです。むしろ、C++の暗黙の変換で。 – rubenvb

+0

@rubenvb編集を確認してください.C++ 11ではこれを解決する方法があります。 – SirGuy

+0

@rubenvbまあまあ、この特定の落とし穴のための治療法で、他のものではありません。 – SirGuy

4

関数の名前は、かっこなしで使用すると、暗黙的に関数ポインタにキャストできます。実際には、参照を解除したり参照したりするときは、関数ポインタや関数ポインタへのポインタなどは残っています。これらの関数ポインタは暗黙的にboolにキャストされます。関数の実際のメモリアドレスを出力したい場合は、voidポインタにキャストします。

cout<<(void*)pr; 
+0

より一般的には、ほとんどのコンテキストでは、関数型(関数名を含む)の式は暗黙的に関数へのポインタに変換されます。例外は 'sizeof'(これは不正)またはunary'& '(関数のアドレスを生成する)の引数です。これは、関数名の後にカッコが続く場合でも適用されます。関数呼び出しには、最初のオペランドとして関数へのポインタが必要です。 –

+1

ところで、 'void *'への関数ポインタをキャストすることは、ほとんどのシステムで動作する可能性が高いですが、その動作が定義されているとは思われません。 (例えば、関数ポインタが 'void *'より大きい場合、変換によって情報が失われる可能性があります。) –

+0

それは不公平です。このコードを動作させるにはコンパイラ拡張が必要です。 (コードは診断を出さなければなりません)。理論的には、コンパイラの拡張機能はその動作を記述する必要があります。 –

関連する問題