2012-03-29 7 views
4

これは簡単ではありませんが、おそらくばかげていますが、 '\ 0'(または0)に初期化された文字ポインタの内容を印刷しようとしたときに、何の状態が残っているのかを理解する必要があります。 3行目にSTRを印刷しようとする試みは、私はする必要があり、いくつかの動作があります後、コンソールに、上記のコードで' 0'に初期化された文字ポインタを標準出力に送信していますか? (C++)

const char* str; 
str = 0; // or str = '\0'; 
cout << str << endl; 
cout << "Welcome" << endl; 

ライン4文句を言わない印刷「ようこそ」:次のコードを見てみましょう知っている?私が1行1-3をと置き換えた場合、cout < < '\ 0' < < endl;次の行の "Welcome"というメッセージがコンソールに正常に出力されます。

注:4行目は静かに印刷できません。警告やエラーメッセージなど(少なくともMinGW(g ++)コンパイラは使用していません)。 MS clコンパイラを使用して同じコードをコンパイルしたときに例外が発生しました。

編集:コードはあなたが「\ 0」にSTRを割り当てる場合にのみ、失敗という概念を払拭するために、私は0に割り当てるコードを修正 - あなたはconst char*値を挿入した場合、以前に

+0

@BoBTFishここの意図はあまりありません。私が尋ねた質問は、それが標準的な出力に違反しているかどうかということです。私がここに持っているものは単なるスニペットです。長い話は、私がライブラリを消費していたことです。特定の関数は初期化された文字列を返すようになっていましたが、そうではありませんでした(明らかにバグです)。だから私の心配は、nullポインタを出力する行為が標準出力を去ったという状態ともっと関係していました。それは私のコードでさえ私が働くことが予想されるものにも影響するからです。 –

+2

あなたのコードは間違っています。あなたはcharとcharへのポインタを混在させました。 – knivil

答えて

12

をコメントしました標準ストリーム(basic_ostream<>)には、が必要です。はnullではありません。 strがnullであるため、この要件に違反し、動作は未定義です。

標準の関連する段落は、§27.7.3.6.4/ 3にあります。

'\0'と直接動作する理由は、'\0'charであるため、要件が壊れていないためです。しかし、Potatoswatterは私にprinting this character out is effectively implementation-definedということを確信しているので、あなたが見ているものは、あなたが望むものではないかもしれません(つまり、あなた自身の小切手を実行します)。ただ、cout << '\0'一部について

+0

バー、彼はポインタにキャラクターをキャスティングしていたのを見たことがありませんでした!しかし、私は '' \ 0 ''という印字が安全だと言うのは正しいとは思わない。私の削除された答えを見てください。 – Potatoswatter

+0

@Potatoswatter C++に関する限り、 ''\ 0' 'の表示には何も問題はありません。いくつかの出力デバイスは特にそれに反応するかもしれませんが、これはちょうどあらゆる文字について真です。 –

+0

@JamesKanze任意の*制御文字について真です。なぜなら、それらが書き込まれたストリームに対して未知の効果を持つことが許されているからです。 – Potatoswatter

3

...

その内容に未定義の効果を持っているテキストモードでファイルやストリームの「文字列の終了」。 C++標準では、テキストの意味(C++ 11 27.9.1.1/2)の事項についてC標準に延期、及びCはかなり厳格である(C99§7.19.2/ 2):

データから読み込まテキストストリームは、そのデータが印刷文字とコントロール文字の水平タブと改行のみで構成されている場合に限り、以前にそのストリームに書き出されていたデータと必然的に比較されます。改行文字の直前にはスペース文字はありません。最後の文字は改行文字です。 '\0'以来

制御文字とcoutがテキストストリームであるあなたがそれを書いたように、結果の出力は読まないかもしれません。

3

char*は、を指します。ヌル文字は、長さゼロの文字列です。印刷には害はありません。

ただし、の値がchar*は別の話です。印刷しようとすると、定義されていない動作であるヌルポインタの逆参照を意味します。クラッシュする可能性があります。

'\0'をポインタに割り当てることは、実際にはうまくいきますが、ポインター変数に文字値を割り当てている場合でも正しくありません。ポインターに割り当てるときは、0またはNULL、またはnullptrをC++ 11に使用します。

+0

** str = 0 **を実行しても同じ動作をすることに言及しました。あなたが提案したものがうまくいくかどうかは分かりません。 –

+0

"動作"は未定義の動作です。 'cout'の' operator << 'にヌルポインタを逆参照するよう要求しています。あなたがプログラムを3行目で壊れた状態にしているので、4行目が機能しないのは驚きではありません。 – Wyzard

+3

ヌル文字*が存在しないので、 'str = '\ 0''を実行すると混乱します。暗黙的にnull *ポインタ*にキャストされ、 'cout << str'を実行すると、*文字ではなく*文字列*を出力する' operator << 'を呼び出しています。 'cout << '\ 0''を実行すると、単一の文字を表示するものが呼び出されます。これは、ポインタの逆参照を伴わない全く異なる関数です。 – Wyzard

7

問題の値が「文字」 (ヌル終了文字列などのターミネータ)でない場合は、'\0'を使用しないでください。つまり、私は、 あなたの混乱の源だと思います。以下のようなもの:

char const* str = "\0"; 
std::cout << str << std::endl; 

は、微細である場合(この 場合、2つ'\0''\0'を含む文字列にstrポイント。何かのように:

char const* str = NULL; 
std::cout << str << std::endl; 

は未定義の動作です。何でも起れる。

歴史的な理由から('\0'および0)、暗黙的に任意のポインタ型に変換され、結果としてNULLポインタが生成されます。

1

は、この例を見てみましょう:あなたが持っている http://ideone.com/8MHGH

主な問題は、strは文字でない文字へのポインタであるので、あなたはそれを文字列に割り当てる必要があることである:str = "\0";

ときそれをcharに代入すると0になり、coutのfailビットが真になり、もはやそれには印刷できなくなります。これが固定されている別の例を次に示します。 http://ideone.com/c4LPh

関連する問題