6
#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
    char array[10];

    for(int i = 0; i<10;i++)
    {
        array[i] = 'a' + i;
    }

    char* test = array;

    printf("%x\n", test);
    cout << hex << test << endl;

}

このための出力は次のとおりです。

bffff94e
abcdefghijN???

同じものを印刷しないのはなぜですか?

4

4 に答える 4

7
cout << hex << test << endl; 

アドレスではなく、文字列を出力します。これは、引数operator<<をとるオーバーロードがありchar const*、このオーバーロードが引数を文字列として扱うためです。

アドレスを出力する場合は、に引数をキャストして、アドレスを出力void*する他のオーバーロードoperator<<が呼び出されるようにします。

cout << hex << static_cast<void*>(test) << endl;

アドレスを16進形式で出力します。

hexアドレスは16進形式で出力されるため、ここではストリームマニピュレータは必要ないことに注意してください。それで

cout << static_cast<void*>(test) << endl;

十分です。

于 2012-06-19T06:43:13.950 に答える
6

プログラムの動作が定義されていないためです。そして、あなたはそれを別のものを印刷するように頼むからです。

の呼び出しprintfは違法であり、未定義の動作になります(そして、決して使用してはならない理由の良い例ですprintf)。フォーマット指定子はunsigned int、引数リストからを抽出し、それを16進数で出力するように指示します。それ以外のものを渡すことunsigned intは未定義の動作です。たまたま、varargsの一般的な実装方法を考えると、 unsignedsとポインターのサイズが同じマシンを使用している場合は、ポインターの値を出力し、そのビットを.であるかのように扱いますunsigned。ただし、他の動作も確かに可能です。(私が間違っていなければ、g ++はこの構成について警告します。一部のプラットフォームでは、クラッシュする可能性もあります。)

の場合std::cout、あなたはそれをpassigしますchar*。定義上、はポインタとしてではなく、(そして確かに)としてではなくchar*、「\0」文字列として扱われます。また、「\ 0」で終了する文字列を指していないため、未定義の動作があります。最後に「\0」を付けることはありません。(これはおそらく 、出力の最後に表示されることを説明しています。しかし、繰り返しになりますが、未定義の動作は、まあ、未定義です。コードは同じように簡単にクラッシュする可能性があります。)unsigned intchar*"N???"

最後に、との両方printfを使用していますstd::cout。2つの間でストリームをフラッシュしない限り、結果は実際には指定されません。(実際には、インタラクティブデバイスに出力する場合は、文字を出力するときにフラッシュが発生するはずです'\n'。ただし、出力をファイルにリダイレクトすると、何かが異なる可能性があります。)

何が欲しいのかはっきりしていません。のアドレスを出力する場合は array、次のようになります。

printf( "%p\n", test );
std::cout << static_cast<void*>( test ) << std::endl;

生成した文字列を出力する場合は、その末尾に「\ 0」を追加して(バッファをオーバーフローさせずに)、次のようにします。

printf( "%s\n", test );
std::cout << test << std::endl;

何を「hex」にしようとしているのかわかりません。文字列の16進表現などはなく、ポインタの表現は実装で定義されており、iostreamのフォーマットパラメータを考慮する必要はありません。(通常、最近のほとんどのマシンでは、16進数になります。ただし、8進数になる場合は数個以上、ベースに関係なく、数値だけではない場合は少なくとも1つ作業しました。)の16進ダンプがarray必要な場合は、ループして各値をunsigned16進数で出力する必要があります。

for ( int i = 0; i < 10; ++ i ) {
    printf( "%x", static_cast<unsigned char>( test[i] ) );
}
printf( "\n" );
std::cout.setf( std::ios_base::hex, std::ios::basefield );
for ( int i = 0; i < 10; ++ i ) {
    std::cout << static_cast<unsigned>( static_cast<unsigned char>( test[i] ) );
}
std::cout.setf( std::ios_base::dec, std::ios::basefield );
std::cout << std::endl;

最後に:キャストについての一言:プレーンcharは署名されている場合と署名されていない場合があります。署名されている場合、それをintまたは に変換するとunsigned、負の値(int)または非常に大きな正の値(unsigned)が生成される可能性があります。したがって、への最初の変換 unsigned charは、範囲内の結果を保証します[0, UINT_MAX]。次に、もちろん、を次のように変換するunsigned char必要がありunsignedます。

  • の場合、それ以外の場合は未定義の動作になりますが、varargとしてを渡すと自動的に;にプロモートされるprintfため、変換は暗黙的です。とunsigned charunsigned

  • この場合std::cout、すべての文字タイプは数値ではなく文字として出力されるという規則があるため(このタイプは関数のオーバーロード解決で使用され、varargまたはanに渡されないためunsigned、暗黙の変換)。

于 2012-06-19T07:47:00.603 に答える
2

testそれ自体がポインタです。つまり、アドレスを格納します。ステートメントprintfは、そのアドレスの16進値を出力します。

マニピュレータは文字列の印刷方法に影響を与えないcout <<ため、ステートメントは文字列全体を印刷します。std::hex整数の印刷方法にのみ影響します。

あなたにできることは

  1. 配列の文字をループします
  2. それぞれを整数に変換し、std::hexマニピュレーターを使用して印刷します

これは次のようになります。

for (int i = 0 ; i < 10 ; ++i)
  std::cout << std::hex << static_cast<int>(array[i]) << '\n';
于 2012-06-19T07:03:55.523 に答える
0

cout << HEX <<
char *を使用して16進char文字列を出力することはできませんが、int、double、floatなどに使用できます。

また、2回目の印刷時に、文字列に文字列が文字化けしているのは、文字列に「\n」を指定していないためです。これは文字列の終わりを意味します。

于 2012-06-19T07:05:18.657 に答える