ページ 1 / 1
C言語の初歩的な質問です。
Posted: 2010年7月18日(日) 00:18
by しろ
こんにちは。ちょっとわからないところを質問です。つまらない質問かもしれませんが、ご教授いただけますと幸いです。
●scanf関数で文字列を読み込む場合の引数について
以下のプログラムをご覧ください。
char a[40];
scanf("%s",a);
char型の配列aに文字列を渡しているわけですが、そもそも文字列の配列は初期化子を代入できないんですよね。
例えば配列aに"xyz"という文字列(文字リテラル)を渡すとして
char a[40];
a="xyz";
というのはC言語の規約上? ダメなのはわかるのですが、それならそもそも上にあるscanfも同じ理由でダメな気がするのですが……
一応scanf関数上のaというのは、配列aの先頭のアドレスであり、そこに文字列を格納していくというのを考えたのですが(ポインタ型の配列だと、初期化子を代入できるので)、それだとchar a[40]ではなく、char *aと宣言しなければならない?
どうもこのあたりが持っている書籍には書いていなかったこともあり、よくわかりません。何卒よろしくお願いいたします。
Re:C言語の初歩的な質問です。
Posted: 2010年7月18日(日) 00:30
by box
> char型の配列aに文字列を渡しているわけですが、そもそも文字列の配列は初期化子を代入できないんですよね。
そういうことはありません。
定義と同時に初期化できます。
char a[40] = "xyz";
> というのはC言語の規約上? ダメなのはわかるのですが、それならそもそも上にあるscanfも同じ理由でダメな気がするのですが……
同じ理由、というのは、どういう理由のことでしょうか?
Re:C言語の初歩的な質問です。
Posted: 2010年7月18日(日) 00:39
by しろ
ご解答ありがとうございます。
>そういうことはありません。
>定義と同時に初期化できます。
すいません。自分のの言い方がまずかったです。char型の配列は宣言をしたあとに初期化子を代入できない(char a[40]; a="xyz";)んですよね。
その意味合いで、scanf("xyz",a);とすると、配列を宣言したあとに、文字列を渡しているので、同じことになってしまうのではないか、ということなのですが・・・・・・
Re:C言語の初歩的な質問です。
Posted: 2010年7月18日(日) 07:25
by へろりくしょん
>すいません。自分のの言い方がまずかったです。char型の配列は宣言をしたあとに初期化子を代入できない
>(char a[40]; a="xyz";)んですよね。
ちょっと重隅をつつくようですが、新ANSI C言語辞典にはこうあります。
初期化子: オブジェクト(変数など)を定義する宣言において初期化をする言語構成要素。
ですから、char a[40]; a = "xyz" の "xyz" は初期化子ではありません。
また、宣言した後で代入することも可能です。
char a[40];
a[0] = 'x';
a[1] = 'y';
a[2] = 'z';
a[3] = '\0';
char a[40] = "xyz";
というコードはあたかも配列aに文字列定数 "xyz" を代入しているかのように見えますが、実際は
char a[4] = {'x', 'y', 'z', '\0'};
のシンタックスシュガーに過ぎません。
配列として宣言された変数が、変数名のみで現れた場合、先頭要素へのポインタを意味します。
ですから、
char a[40];
a = "xyz";
というコードは
char a[40];
&a[0] = "xyz";
と等価となります。
代入出来ない理由は一目瞭然ですね。
>一応scanf関数上のaというのは、配列aの先頭のアドレスであり、そこに文字列を格納していくというのを考え>たのですが(ポインタ型の配列だと、初期化子を代入できるので)、それだとchar a[40]ではなく、char *aと>宣言しなければならない?
ポインタ型の配列というのが今ひとつ分かりませんが、配列へのポインタですか? ポインタの配列ですか?
ちなみに、
char *hoge[40]; //ポインタの配列
char (*foo)[40]; //配列へのポインタ
です。
[/url]が配列としての意味を持つのは唯一宣言時だけです。
char *hiho;
char baa[40];
は両方とも、式の中での型は char* 型になります。
と、言うことを聞きたいのでしょうか。
Re:C言語の初歩的な質問です。
Posted: 2010年7月18日(日) 09:55
by しろ
へろり様
ご解答ありがとうございます。
初期化子については理解できました。
えーとお伺いしたいのは、どちらかというとscanf関数のほうでして
a[4];
scanf("%s",&a);
で例えば「ptr」と打ち込むと、結果的に、a[4]={'p','t','r','\0'}となるわけですが、なぜそうなるのか理解できないのです(そういう関数だからといえばそれまでですが)。
&aが配列の先頭のポインタで、それにptrをいれるということは結果的に&a[0] = "xyz"; と同じなのではないか? という疑問です。
Re:C言語の初歩的な質問です。
Posted: 2010年7月18日(日) 11:10
by へろりくしょん
>a[4];
>scanf("%s",&a);
これは、scanf("%s", &a[0]); もしくは scanf("%s", a); のつもりですよね。
>&aが配列の先頭のポインタで、それにptrをいれるということは結果的に&a[0] = "xyz"; と同じなのではないか? という疑問です。
先に述べました通り、配列として宣言された変数が、変数名のみで現れた場合、先頭要素へのポインタを意味します。
関数の引数にポインタを渡すだけで、なぜ、&a[0] = "xyz"; というコードと等価だと思うのかちょっと分からないのですが。
scanf() 関数では、引数に受け取ったポインタのアドレスから1つ1つ文字を代入してくれている。 とは考えられませんか?
Re:C言語の初歩的な質問です。
Posted: 2010年7月18日(日) 11:23
by しろ
>>scanf() 関数では、引数に受け取ったポインタのアドレスから1つ1つ文字を代入してくれている。
なるほど、scanf関数はそういう関数ということですね。理解できました。またわからないことがあれば質問させていただきます。ありがとうございました。
