C言語学びたての初心者です。
今sscanfについてやっているのですが、文字列を受け取る場合には変数にそのまま代入できますが
数値を受け取る場合には以下のように書かないといけないと聞きました。
C
1int n; 2sscanf(buf,"%d",&n);
なぜ数値の場合にアドレス指定が必要になるのでしょうか?
変数を使って計算をしたり値の更新は行えるのに、なぜこの場合だと番地を指定しないといけないのでしょうか?
文字列は恐らく配列として扱われていることは理解しているのですが、この辺りがまだ頭の中で整理できていないです。
よろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
ベストアンサー
配列と通常の変数の違いの前に、なぜ、アドレスを渡さなくてはならないのか?という点についてです。
C言語では、関数の引数に指定された変数は、それ自体が関数に渡される訳ではなく、
その変数に格納されている値が取り出され、その値だけが関数側に渡されるという仕組みになっています。
これを「値渡し」と呼ぶのは他の方々も書かれているとおりです。
例えば、こんなコードを考えてみます。
C
1void func(int x){ 2 printf("func1:%d\n",x); //関数が受け取った値 3 x = x + 2; 4 printf("func2:%d\n",x); //関数内で書き換えた値 5} 6 7int main(){ 8 9int x = 3; 10func(x); 11printf("main:%d",x); //main関数内での値 12 13return 0 14}
これを動かすと分かりますが、関数が受け取ったものは、あくまでオリジナルの値のコピーに過ぎないのです。
その為、関数内でいかにその値を書き換えようとも、オリジナルの変数の値に影響は及ぼしません。
逆に言うとこれは、関数内から呼び出し元へは結果を返せない、と言うことになります。
そこで、ポインタ(アドレス)を使います。
アドレスを渡したとしても、アドレスの数値がコピーされて渡される事には変わりありません。
しかし、渡されたのがアドレスであれば、それがコピーであっても、アドレスの値の先にあるデータを見る事で、オリジナルの変数と同じメモリにアクセスする事ができます。
これにより、オリジナルの変数の値を関数の内側から書き換える事ができ、変数を通じての値のやり取りが可能になるのです。
その為に、値を返してほしいsscanfでは、変数のアドレスを引数に渡します。
ここから先の、文字配列が省略して書いているだけで実は同じくアドレスを渡しているというのは、他の方々の言われているとおりです。
投稿2020/05/04 22:47
総合スコア1218
0
質問者さんが言う「文字列を受け取る場合には変数に直接代入できる」とは、恐らく以下のようなコードを指して言われているのだと思いますが、
C
1char msg[256]; 2sscanf(buf, "%s", msg);
これは一見、msg
と言うchar
型の配列に直接代入されているように見えますが、実はそうではなく、char msg[256]
配列の先頭のアドレスをsscanf
の引数として渡しています。以下のようにも書き換えられます。&msg[0]
と書くのがプログラマーにとって冗長なので、多くの場合にmsg
と記述するだけの話なのです。
C
1char msg[256]; 2sscanf(buf, "%s", &msg[0]);
したがって、int
型の整数にsscanf
で取り出した値を代入する際に記述するのと同様の意味になります。
C
1int num; 2sscanf(buf, "%d", &num);
立場を変えて、sscanf
と言う関数を質問者さん自身が実装することを考えてみてください。sscanf
に渡されてくる変数が、「値渡し(call by value)※」で渡されたものであると、関数内で変更することはできません。ここで、値を呼び出し側のmain
へ変更して返したい場合は、アドレス、つまりポインターで渡すことで「(call by reference)※」sscanf
関数の中から作用させることができます。これは文字列(char
型の配列)であろうと、int
型であろうと、すべて同じことが言えます。
**※**C言語において「call by value」、「call by reference」と言う用語を使うことは説明上の慣例である場合を除き、不適切である可能性があります。ご注意ください。
投稿2020/05/04 09:41
編集2020/05/05 01:55総合スコア9256
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
文字列を受け取る場合には変数にそのまま代入できますが
本当ですか?
C
1 char s[100]; 2 sscanf(buf,"%s",s);
とかしてませんか? ここでの s
は確かに変数ですが、配列のアドレスとなります。数値の場合も同様に、
C
1 int n[100]; 2 sscanf(buf,"%d",n);
と書けます。
投稿2020/05/04 09:32
編集2020/05/04 09:39総合スコア6385
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
元々文字列の場合は、アドレス指定になっています。
int の場合は、& を付けないと値のコピーになるので sscanf で値を書き込んでも main 側に戻すことができません。
投稿2020/05/04 09:16
編集2020/05/04 09:28総合スコア1773
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/04 09:29
2020/05/04 09:42
2020/05/04 09:57
2020/05/04 10:01
2020/05/04 10:05
2020/05/04 10:09
2020/05/04 23:45 編集
2020/05/05 01:46 編集
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/05 02:59
2020/05/05 03:18
2020/05/05 23:30