- 締切済み
C言語のポインタと文字列についての質問です。
Cを勉強中です。 char *c; c ="ABC"; printf("%s",c); と書くのは危険だから絶対だめだというサイトと、別に書いても大丈夫だというサイトがあるのですが、 どちらが正しいのですか? 後、もし危険ならば簡単になぜか教えていただければ嬉しいです。
- みんなの回答 (8)
- 専門家の回答
みんなの回答
- nissii202
- ベストアンサー率33% (1/3)
No.7 さんの回答通り、char *cで宣言した変数にリテラルを代入すると リテラルへの書き込み操作を記述出来てしまうため、書き込み操作が行われないよう const char *cと宣言すべきということではないでしょうか。 リテラルへの書き込み操作はプログラムが異常終了したりします。 constが付いていない変数は基本的に書き込みが行われるものとして宣言し 書き込みを行わないのであればconstを付けて宣言する方が良いと思われます。
- jjk65536
- ベストアンサー率59% (66/111)
Cを勉強中ということで、別の書き方も提示しておきます。 char *c; c = "ABC"; c[0] = 'a'; 3行目はリテラルの上書きになるため、C言語では許されていません。 No.5の方のはmallocで確保しても発生する問題なので、 別件と考えたほうが良いと思います。 上記をしたい場合は char c[] = "ABC"; c[0] = 'a'; のように書きます(一例です)。 これは、リテラルではなく文字列配列の先頭を書き換える行為なので 問題がありません。
- Tacosan
- ベストアンサー率23% (3656/15482)
それは複数のミスが混ざっていて回りくどい>#5. char *c = "ABC"; *c = 'a'; の方が端的.
- luka3
- ベストアンサー率72% (434/598)
これだけでは問題ないですが、では具体的にどうするとダメなのかを簡単に説明すると、 char *c; c ="ABC"; printf("%s",c); strcpy(c, "DEFG"); これだけでこのプログラムがどう動くか誰にもわからなくなります。 "ABC\0"の4バイトの領域に"DEFG\0"の5バイトを書き込むと、"ABC\0"の後ろにあるメモリが破壊されることになるからです。 優秀なコンパイラなら警告やエラーを出すかもしれませんし、優秀なCPUならメモリ破壊直前に止まるかもしれません。 しかし、プログラマであればこんなあいまいな作法はしない方がよいのです。 "ABC"という文字列リテラルに対して const char *c; と宣言しておけば、strcpyの第1引数でconst char *はダメですとコンパイラが教えてくれます。 危険は未然に防ぐ、ということをそのサイトは教えたかったのではないでしょうか。
- k_kota
- ベストアンサー率19% (434/2186)
これだけなら問題無いですけど、わざわざポインタを使う意味も無いかなと思います。 cが指す文字列が固定ならこのような書き方はリスクがあるがメリットが無いです。 文字列が可変ならこの用に書くしか無いです。 要するに使い方に合うかどうかってことですかね。 ポインタだと使い方失敗した場合に結構厄介になるし、 ただの配列ですむなら多少見通しが効きやすい。 この部分だけ正しい正しくないと言うのは問題としておかしいと思いますが、 ポインタを理解すれば分かると思います。
- D-Matsu
- ベストアンサー率45% (1080/2394)
ほとんどのコンパイラでは2行目の文字列リテラルは書き換え不能領域に配置され、うっかりその領域を変更しようとしたらエラーになるのでcの型はchar *よりはconst char *としておいた方が明らかに安全ではあります。 が、先の回答にもあるように質問のコードだけであれば「書き換えるコードが存在しない」のでchar *でも特に問題にはなりません。 ただし、潜在的な問題を考えればこういうコードを書く際の型はconst char *にする癖は付けといた方がいいでしょう。
- notnot
- ベストアンサー率47% (4900/10359)
想像ですが、おそらくだめと書いてあるサイトに載っているプログラムは、 char *c; c ="ABC"; printf("%s",c); とは違うプログラムで、そこには何か書いては駄目なものが含まれているんだと思います。 もし、一文字も違わず上記のプログラムがだめと書いてあるサイトなら、そのサイトの書いていることは間違いです。
char *c; // cは、charをさすポインタ変数である c= "ABC"; // cのあたいとして、ABCの先頭アドレスを代入する printf("%s",c); // cを文字列として、文字列プリント ということで、危険だから、絶対ダメだ、というサイトは、とんでもサイト。 べつに、問題はない。 2つめの代入なしで、変数宣言とprintfだけなら、不定値で、文字列プリントしようとするので、クラッシュしかねないけど。