2011-12-27 19 views
0

私はMicrosoft Visual Studio環境で作業しています。文字列の割り当て

1 a 
1 a 

初期化されていないdes[0]を意味:私は奇妙な行動結果が

char *src ="123"; 
char *des ="abc"; 
printf("\nThe src string is %c", src[0]); 
printf("\tThe dest string is %c",dest[0]); 

des[0] = src[0]; 

printf("\nThe src string is %c", src[0]); 
printf("\tThe dest string is %c",dest[0]); 

に出くわしました。 srcは文字列の最初の要素を指しています。私は規則でこれがうまくいくはずだと思います。

+1

言語に質問にタグを付けて、人々があなたの話を知っているようにしてください。 – Oded

+0

C++を使っているなら、なぜprintfとCスタイルの文字列を使っているのですか? –

+0

@CodyGray:申し訳ありません。私はプラットフォームとしてC言語を使用しています。私はタグを編集しました。 – vinaygarg

答えて

1

srcとデスが文字列リテラルで初期化されているので、その種類は実際にconst char *、ないchar *する必要があります。

const char * src ="123"; 
const char * des ="abc"; 

いずれのメモリにも割り当てられていないメモリは、あらかじめ定義された定数を指しています。したがって、文des[0] = src[0]は未定義の動作です。あなたはそこに定数を変更しようとしています!

まともなコンパイラが実際にchar *からconst char *からの暗黙的な変換について警告すべきである...

C++を使用している場合は、代わりにprintfstd::string代わりのchar *、およびstd::coutを使用することを検討してください。

3

これは未定義の動作です:

des[0] = src[0]; 

は、代わりにこれを試してみてください:

char des[] ="abc"; 
+0

ありがとうございます。はい、それは動作します。しかし、両方の場合にそうではありません、デは同じ場所を指しているでしょう。そして最終的に 'des [0]'は '*(des + 0)'と等価です。定義されていない動作によって、あなたはCの仕様を参照していますか? – vinaygarg

+0

@vinaygargそれは同じことではありません。はい、私はCの標準について話していますが、私はこの点でC++標準が似ていると思います。 – cnicutar

1

ISO/IEC 14882のセクション2.13.4(プログラミング言語 - C++)と言う:必要に応じて二重引用符で囲まれた(2.13.2で定義されている)

  1. 文字列リテラルは、文字のシーケンスであり、 "..."またはL "..."のように、文字Lで始まります。 Lで始まらない文字列リテラルは、通常の文字列リテラルであり、狭い文字列リテラルとも呼ばれます。通常の文字列リテラルは、「配列のn const char」と静的記憶域の長さ(3.7)を持ちます.nは、以下に定義される文字列のサイズであり、指定された文字で初期化されます。 ...

  2. すべての文字列リテラルが区別されている(つまり、重複しないオブジェクトに格納されている)かどうかは、実装定義です。文字列リテラルを変更しようとすると、は未定義になります。

0

vinaygargdes[0]が初期化されていないことを意味します。 srcは文字列の最初の要素を指しています。私は規則でこれがうまくいくはずだと思います。

まず、* srcと* dstがポインタとして定義されていることを覚えておく必要があります。

それでは、正確に「123」と「abc」が何であるのか、なぜそれを変更できないのか自分自身に尋ねなければなりませんか?短いストーリーを短縮するには、それはread-onlyであるアプリケーションメモリに保存されます。どうして?実行時にコードに使用できるようにするには、文字列をプログラムに格納する必要があります。理論的には、非const char*const char *に割り当てるためのコンパイラの警告が必要です。なぜそれがread-onlyですか? exeとdllのメモリは何らかの形で上書きされないように保護する必要があるため、バグやウイルスの実行コードの変更を止めるには読み取り専用でなければなりません。

どうすればこの文字列を変更可能なメモリに入れることができますか? Cにおいて

// Copying into an array. 
const size_t BUFFER_SIZE = 256; 
char buffer[BUFFER_SIZE]; 
strcpy(buffer, "abc"); 
strncpy(buffer, "abc", BUFFER_SIZE-1); 
+0

@pmg私の謝罪は、執筆時点でのCのみの要件を認識していませんでした。更新しました。それを指摘してくれてありがとう。 –

1

、例えば"123"として文字列リテラルはchar(C++でconst char)の配列として格納されています。これらの配列は、プログラムの存続期間にわたって利用できるようにメモリに格納されます。文字列リテラルの内容を変更しようとすると、動作が未定義になります。コンパイラとプラットフォームによっては時には "うまくいく"、時にはそうではないので、文字列リテラルを書き込み不可能なものとして扱うのが最善です。

"N要素配列T"の式は、 "Tへのポインタ"型の式に変換され、その値は配列の最初の要素の位置であることに注意してください。もし

char *src = "123"; 
char *des = "abc"; 

を書くとき

したがって、"123"と​​が「charへのポインタ」を「charの3要素配列」から変換され、そしてsrc"123"'1'を指します、des'a'を​​に示します。再び

、あなたが

des[0] = src[0]; 

を書くときに、コンパイラはにそれを完全に無視してから、その文にそれが望んでいる任意の方法を治療して自由である、未定義の動作では、文字列リテラル結果の内容を変更しようとしますその間に何かをすることを期待しています。つまり、文字列リテラルまたはそのポインタは、strcpystrcatmemcpyなどの呼び出しのターゲットパラメータとして使用することはできず、strtokのような呼び出しのパラメータとして使用する必要もありません。

関連する問題