C言語関係掲示板

過去ログ

No.1233 文字列リテラルの変更

[戻る] [ホームページ]
No.16430

K&Rを読んでいて(ポインタと配列)
投稿者---lala(2004/08/30 20:49:36)


 Cの勉強をしていて、幾つか関係の本を読んだ後に、今K&Rを読んでいます。
ポインタの所で疑問が出たので質問します。
char amessage[]="now is the time"
  char *pmessage ="now is the time"
の違いについて説明してあったのですが(p127)、ここで後者のpmessageについて『文字列の内容を変更しようとすると不定になる』とあるのですが、これは前者のように一定のメモリを指してるのではなく"now is the time"というのが一つの塊となっているという事ですか?ここが少し分かりません。ご指導お願いします



No.16431

Re:K&Rを読んでいて(ポインタと配列)
投稿者---Sciggepy(2004/08/30 21:11:35)


処理系依存ということではないでしょうか。
私の処理系で試したところ、
#include <stdio.h>

int main(void)
{
    char *s="abcdef";
    s[0]='g';
    printf("%s",s);
    return 0;
}

結果:
Boland C/C++ Compiler 5.5.1
gbcdef

gcc 3.2.3(MinGW)
Segmentation fault(異常終了)
となりました。
BCCでは、"abcdef"は静的領域に置かれ、書き込み可能になっていますが、gccではコード領域に置かれるようです。



No.16433

Re:K&Rを読んでいて(ポインタと配列)
投稿者---lala(2004/08/30 21:33:50)


 処理系依存の為不定となってしまうということですか。自分だけでは気づけませんでした。
ありがとうございます。もっと勉強して色んな原因に気付けるよう努力します。



No.16434

Re:K&Rを読んでいて(ポインタと配列)
投稿者---シャノン(2004/08/30 21:34:36)


> Cの勉強をしていて、幾つか関係の本を読んだ後に、今K&Rを読んでいます。
>ポインタの所で疑問が出たので質問します。
> char amessage[]="now is the time"
>  char *pmessage ="now is the time"
>の違いについて説明してあったのですが(p127)、ここで後者のpmessageについて『文字列の内容を変更しようとすると不定になる』とあるのですが、これは前者のように一定のメモリを指してるのではなく"now is the time"というのが一つの塊となっているという事ですか?ここが少し分かりません。ご指導お願いします

わかりやすく言えば、char[] の宣言と char* の宣言は同一ではなく、
後者の変更はしてはいけませんよ、ということです。

なぜ変更してはいけないかと言うと、変更したときの振る舞いが
C 言語の規格に定められていないからです。
これが「不定になる」ということです。

振る舞いが不定とはどういうことかといいますと、
決められていないのですから、コンパイラはどんなことをする
コードを生成してもいいわけです。

あたかも char[] と同じように振舞うのも合法ですし、
突然プログラムが不正終了しても合法ですし、
ハードディスクをフォーマットしても合法ですし、
家が火事になっても文句は言えません。


No.16435

Re:K&Rを読んでいて(ポインタと配列)
投稿者---シャノン(2004/08/30 21:36:02)


>なぜ変更してはいけないかと言うと、変更したときの振る舞いが
>C 言語の規格に定められていないからです。
>これが「不定になる」ということです。

失礼。
「不定」ではなく「未定義」でした。


No.16436

Re:K&Rを読んでいて(ポインタと配列)
投稿者---lala(2004/08/30 21:41:11)


Sciggepyさんの言っていた処理系依存も『未定義』って事から来るってことなんですね。いやはや、良くわかりました!!『未定義』->『処理系依存』か。お二人ともどうもありがとうございました。


No.16438

Re:K&Rを読んでいて(ポインタと配列)
投稿者---YuO(2004/08/30 22:13:03)


>Sciggepyさんの言っていた処理系依存も『未定義』って事から来るってことなんですね。
>『未定義』->『処理系依存』か。

未定義と処理系依存は違います。

未定義というのはシャノンさんの書かれているように,
標準に振る舞いが定義されていないことで,根本的に間違ったことをした場合に起きます。
処理系は何をしても良いし,何もしなくても良いです。

処理系依存というのは,正しい振る舞いではあるものの,どのような振る舞いをするかは処理系に委ねられていて,その振る舞いは処理系が文書化する必要があるものです。
#文書化しなくて良い物は「未規定」と呼びます。

処理系依存の項目には,各型のサイズ,fprintf等で%pを使ったときの表示形式,malloc(0)に対する戻り値などがあります。


さて,問題の文字列リテラルの変更ですが,これは未定義の振る舞いとなっています。
#ISO/IEC 9899:1999 6.4.5 String literals / Paragraph.6
つまり,文字列リテラルを変更してはいけません。



No.16458

Re:K&Rを読んでいて(ポインタと配列)
投稿者---lala(2004/08/31 18:03:13)


 分かりました。皆さん分かりやすい説明ありがとうございました。
皆さんの意見を参考に大学で本を探して読んでみました。もっと勉強させていただきます。