プロが教える店舗&オフィスのセキュリティ対策術

当方c言語初学者なのですがscanfを使ってポインタに文字列を入力したいのですがバグが発生して進みません・・・どういうことなのでしょうか?
#include <stdio.h>

int main(void)
{
char *a;

scanf("%s", a);
printf("%s", a);

return (0);
}

*aをa[128]; のように配列に変えるとうまくいくことはなんとかわかるのですが・・・助けてください(^_^;)

A 回答 (6件)

ポインターというのは格納された値のアドレスのメモリーを指すための変数です。


一方、配列はデータを格納するためのメモリーを確保して、その先頭のアドレスが入っていますよ。

char *a;
scanf("%s", a);

と書くと、aを初期化せずにaの指す先にscanfで文字列を入れます。
大抵、プログラムが書き込むことを許されていないメモリーに書き込みを行おうとしたことを検出したOSからそのプログラムは強制終了されます。

char *a = "aaaaa";
scanf("%s", a);
となっているとどうなるか。
aは"aaaaa"が格納されているメモリーを指すように初期化されます。
ただ、大抵"aaaaa"は固定値を入れるために書き込みができないメモリーに格納されています。
よって、scanf("%s", a);も書き込みができないところに書こうとしたことをOSに検出され、強制終了となります。

2つ方向があると思います。
1. char a[128];のように宣言し、スタック上にメモリーを確保し、その先頭アドレスが入っているaを渡す方法。
2. mallocなどでヒープにメモリーを確保する方法。

1だと、
char a[128];
scanf("%127s", a);
のように書き、scanfで読み込んだ分をaから始まるメモリーに書くことになりますが、char a[128];で配列を確保しているので書き込みを行うことができ、強制終了はされません。

2だと、
char *a = malloc(128);
scanf("%127s", a);
printf("%s", a);
free(a);
のように書きます。
配列はスタック上に取られ、スタック上に取った値はプログラムがその関数を抜けるときに自動的に解放されますが、mallocで確保したメモリーは自動で解放されないので自分でfreeを呼んで開放する必要があります。

%127sがそろそろ気になっていると思います。
こうやって127文字までしか受け取らないようにscanfに指示しています。
C言語では文字列の最後は終了を示すNUL文字が入るので、確保したメモリーよりも1少ない値となっています。

というわけで、ちゃんとメモリーを確保してからscanfで書き込みましょう。ポインターはあくまでどこかのメモリーアドレスを指すだけで、指した先がちゃんと確保されているかどうかは知りませんから。
    • good
    • 3
この回答へのお礼

ありがとうござしました。何とか先に進めそうです!

お礼日時:2014/03/29 18:57

char *a = "aaaaaaaaaaaaaaaaaaaaaaaaaaaa";


で「あなたが自由にできる領域」を確保することはできません.
    • good
    • 0

ポインターと配列


は、全く別物であることを勉強してください。
    • good
    • 0

通常は、malloc などで、領域確保します。


あと、scanf のフォーマット指示の s には、
確保した領域 - 1 を指定します。
リテラル値で、ポインタを初期化して、
その領域に書き込むことは、禁止されていると思います。

#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *a = (char *) malloc(128);
scanf("%127s", a);
printf("%s", a);
return 0;
}
    • good
    • 1

char *a;


と書いただけでは文字列(あるいは文字列を格納する場所)がどこにあるかということを指し示す変数を用意しただけです。実際の領域は何らかの手段で用意する必要があります。
しかも、ただ上記のように書いただけでは、指し示す先はいったいどこなのかわけのわからない場所です。書き込みが禁止されているところや重要なデータが入っているところを指している恐れがあり、危険な状態です。

この回答への補足

char *a = "aaaaaaaaaaaaaaaaaaaaaaaaaaaa";
のようにして領域を確保すればいいのでしょうか?

補足日時:2014/03/26 19:14
    • good
    • 0

char *a ;


だけでaに実在する配列の先頭アドレスを代入してないという事は無いですか。
char *a ;
char s[128] ;
a=s ;
とか。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A