質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

1243閲覧

ポインタが指す文字列リテラルの書き換え

salah0615

総合スコア49

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2019/06/09 05:46

ポインタが指す文字列リテラルの中身を書き換えてはいけない(処理系に依存する)。
とあったのですが、なぜダメなのでしょうか。

「ポインタは文字列リテラルを記憶している領域(の先頭アドレス)を指しているため,ポインタの指している内容を変更しようとすると予期せぬエラーが発生します」

という記事を見ましたが、ポインタptrに格納されているのはアドレスで、別にアドレスを変更するわけではなく、内容を変更するだけだから問題ないように思うのですが。

そもそも、文字列リテラルに限った話だと思うのですが、なぜそれに限ったことなのかもわかりません。
例えば

c

1int a = 178; 2int *ptr; 3ptr = &a; 4*ptr = 180; 5printf("%d", a); //180 6printf("%d", *ptr); //180

というようになると思いますが、これは正常に動作します。

なんのために文字列リテラルの中身を変更するとエラーが発生するようになっているのか、また何故文字列リテラルに限ったことなのか教えていただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

内容を変更するだけ

文字列リテラルは「定数(扱い)」です.
定数とは「値が変わらない」ということです.
ですので(出来るか出来ないかは別として)内容を変更してはいけないということになります.

投稿2019/06/09 06:21

jimbe

総合スコア12545

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

salah0615

2019/06/09 07:50

ありがとうございます。
guest

0

理由は、ANSIの規格で文字列リテラルを書き換えた際の動作は未定義となっているからです。
未定義というのは何が起こるか分からないということを意味しています。

例えば、文字列リテラルの先頭アドレスがリードオンリーのROM領域に割り当てられると書き換えは不可ですよね。

投稿2019/06/09 05:56

TaroToyotomi

総合スコア1430

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

salah0615

2019/06/09 07:50

わかりやすかったです。ありがとうございます。
guest

0

組込系では文字列リテラルや定数(constの付いたもの)はROMに格納します。また、重複する文字列を同じ領域に格納する処理系も有ります。そのへんの考慮だと思いますが?
(PC使っていると不思議に思うかもしれませんが・・・)

投稿2019/06/09 07:02

編集2019/06/09 07:04
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

salah0615

2019/06/09 07:50

ありがとうございます。
guest

0

ベストアンサー

こんにちは。

昔、以下のコードが通る処理系が存在しました。(C++では通らないです。C言語も今は通らないかも。)

#include <stdio.h> void func() { char* title="Foo!!"; printf("func()\n"); printf("%s\n", title); title[0]='B'; printf("%s\n", title); } int main() { func(); return 0; }

結果は次のようになる筈です。

func() Foo!! Boo!!

そして、もう一度funcを呼び出すと以下のような結果となる処理系が実際に存在ました。
titleの指す先のリテラル文字列を書き換えていますから、ある意味素直な実装と思います。

func() Boo!! Boo!!

これは凄く嫌ではないでしょうか? ですので、このような記述は未定義動作となっているのだと思います。

投稿2019/06/09 06:10

編集2019/06/09 06:12
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

salah0615

2019/06/09 07:49

ありがとうございます。 なんのために、を答えてくださったのでベストアンサーとさせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問