2013-07-23 6 views
37

これをポインタではありません。なぜこうなった?はcout <<のchar *引数を印刷した文字列で、値

+0

「こんにちは」を取得していませんか? – sth

+0

出力として 'h'が得られますか?それは起こるべきではありません。 'hello'を出力として取得する必要があります。ここに投稿したコードが間違っていて、誤植やコピー&ペーストのエラーではないと確信していますか? –

+0

@sth彼はしています:http://ideone.com/IDudH3 – dotixx

答えて

8

あなたは、このようにコードを変更する必要があります。

cout << static_cast<const void*>(terry); 

問題は<<オペレータは、文字列の内容を印刷するためのCスタイルの文字列へのポインタのためにオーバーロードされていることです。その代わりに生のポインタにキャストすると、iostreamsを使って必要に応じてポインタを出力するというデフォルトの動作が得られます。

-1

"hello"は文字列、つまりchar配列です。 const char*はこの配列へのポインタなので、このポインタを間接参照すると、最初の要素の値が得られます。

あなたは

int a[] = {1, 2, 3}; 
int *b = a; 
cout << *b << endl; 

を持っている場合、あなただけの1が印刷され得るようにそれはあります。

+0

なぜメモリアドレスを取得していないのですか? –

+1

@ Mr.Puff charポインタのメモリアドレスを取得したい場合は、 'ostream <<'演算子が文字列へのcharポインタのためにオーバーロードされるため、これをvoidポインタの前にキャストする必要があります。 –

53

std::coutは、char *をCスタイルの文字列(の最初の文字)へのポインタとして扱い、そのまま出力します。

cout << (void *) terry; 

(またはあなたが鋳造心配している場合const void *キャストを使用:あなたの代わりにアドレスをしたい場合は、あなただけのそのように、のようなものを扱わないポインタにキャストすることができますこの特定のケースでは問題にならないもの)を使用することができます。


あなたは現実主義よりも純粋主義者のより多くのなら、あなたもの線に沿って、C++ static_castを使用することができます。それは、この特定の場合には不要なのですけれども

cout << static_cast <const void *> (terry); 

、へのキャストvoid *は正常に動作します。

#include <iostream> 
int main (void) { 
    const char *terry = "hello"; 
    std::cout << terry << '\n'; 
    std::cout << (void *) terry << '\n'; 
    std::cout << (const void *) terry << '\n'; 
    std::cout << static_cast<const void *> (terry) << '\n'; 
    return 0; 
} 

出力(アドレスがご使用の環境で異なる場合があります):static_castを使用しているとき、あなたはドンを確実にしなければならない、ということ

hello 
0x8048870 
0x8048870 
0x8048870 

注次のサンプルコードは、アクション内のすべてのこれらのオプションを示していstatic_cast <void *>(それはconst_castのためのものです)とのconstnessを投げ捨てようとしません。これは、新しいC++のキャストによって行われるチェックの1つであり、古いスタイルのキャストにはこの制限がありません。

+1

'char *'の値はCスタイルの文字列として扱われません。 Cスタイルの文字列(の最初の文字)の*ポインタ*として扱います。 –

+1

@Keith、意味論上の問題、それについての謝罪。私は、Cスタイルの文字列として出力することを意味していました。私は明確にします。 – paxdiablo

+0

「セマンティクス」という言葉は、それが重要でないということを意味するのでしょうか?そうではありません。 –

1

coutは、char *を渡すとオーバーロードされるので、Cスタイルの文字列へのポインタとして出力されます。したがって、それはヌル終了文字に当たるまで文字を出力します。

coutの代わりにprintfを使用した場合は、そのアドレスが表示されます。ポインタを別の型、例えば(void *)にキャストし、アドレスも取得できます。std::cout

+0

'printf'自体がどのように印刷するかを決めるのではなく、C++で同じ型を使用するのと同じ方法で、正しい書式指定子を使用する必要があります。例えば、 '%s 'を持つ' printf'は 'char *'を持つ' cout'とまったく同じ問題を持ちます。ポインタを取得するには、書式指定子 '%p'を使用します。 – paxdiablo

11

<<演算子はオーバーロードされます。その動作は、右オペランドのタイプによって異なります。 (これは、すべてのoperator<<という名前の、実際にはいくつかの異なる機能です。コンパイラが呼び出すするかを決定します。)

あなたはそれをchar*またはconst char*を与えた場合、それは(の最初の文字)へのポインタとしてのオペランドを扱いますC-スタイル文字列、およびその文字列の内容を印刷します

const char * terry = "hello"; 
cout << terry; // prints "hello" 

あなたはそれをchar値を与えた場合、それは文字としてその値を出力します。

cout << *terry; // prints "h" 
cout << terry[0]; // the same 

あなたはそれを標準のポインタを与える場合E void*、それは(典型的には進いくつかの実装で定義されたように、)そのポインタ値を出力:Cスタイルの文字列へのポインタが特殊なケースであり、唯一のよう

cout << static_cast<const void*>(terry); // prints something like 0x4008e4 

char*又はconst char*を治療しますoperator<<にオペランドの値以外の値を表示させる(私が考えることができる)ものがあります。この理由は、 "string"型を持たず、char*ポインタを介して文字列を操作するCのC++のルーツに戻ります。

operator<<には、std::stringなどのさまざまな整数型と浮動小数点型のオーバーロードが多数あります。

+0

私が考えることができる別の「特別な」ケースは、(関数がストリームマニピュレータの署名を持たない限り) 'bool'オーバーロードを選択する関数ポインタを出力しようとしていることです:http://ideone.com/OkutRD(確かに'bool'に変換されたポインタの"値 "を出力するので、これは' const char * 'の場合よりも「あまり特別ではない」) –

関連する問題