最近、C言語の勉強をはじめました。


今はポインタと文字列の関係について勉強していて、
下記のようなサンプルプログラムを作成しました。

期待していた結果は、"abc" だったのですが、
実行したところセグメントエラーとなってしまいました。

原因(考え方の誤り)と修正例を教えてください。
# このソースでやりたかったことは「文字列を指定文字数で破壊的に切る」です

よろしくお願いします。

【環境】
CentOS 5
gcc 3.4.4

【ソースコード】
#include <stdio.h>

int main(void)
{
 char *str = "abcde";
 char *p;

 p = str;
 
 int i = 0;
 for (i = 0; i < 3; i++) {
  str++;
 }

 *str = '\0';
 printf("%s\n", *p);
 return 0;
}

回答の条件
  • URL必須
  • 1人2回まで
  • 登録:
  • 終了:2008/02/27 00:13:26
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答1件)

id:Bookmarker No.1

回答回数191ベストアンサー獲得回数34

id:kanouk

FAQなんですね。ありがとうございました。

2008/02/27 00:06:15
  • id:Vacuum
    【ソースコード】
    #include <stdio.h>

    int main(void) {

     char str[16];
     char *p;

     strcpy(str,"abcde");
     p = str;
     str[3] = '\0';
     printf("%s\n", *p);
     return 0;
    }

    ならオッケ~ということですね。
  • id:JULY
    http://www.linux.or.jp/JF/JFdocs/archive/GCC-HOWTO.html#ss4.3

    上記ページの「書き込み可能な文字列(プログラムがランダムに停止する)」のところで gcc での挙動に関して書かれていて、コンパイルオプションで、定数を通常のデータセグメントに置く事ができるようです。
  • id:HISI
    ひょっとして、
    最後のprintf("%s\n",*p);の箇所のpの表現がマズいとか。

    p自身がポインタなので、
    *pとしたらpが示した先のメモリに格納された値、つまり"a"(16進数で0x61)の値のことを示します。
    (ポインタの前に*をつけると、「そのポインタが示している先のメモリの中身」が値になります)

    そのため"%s"(文字列のポインタを要求する書式)は
    ポインタpのアドレスではなくて、
    アドレス0x00000061(32ビットCPUであれば)から文字列を読もうとして
    アクセス違反が起きるでしょう。

    char *p;と宣言するときの*の役割と
    a = *p;などと参照するときの*の役割が違うので、注意が必要です。
  • id:takabow
    id:HISIさんがおっしゃるように、
     × printf("%s\n",*p);
     ○ printf("%s\n",p);
    ですね。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません