- 締切済み
[C言語] 関数の配列引数の扱いについて
C言語習得中の文系学生です。現在、データ構造(リンクリスト、ツリー構造)を勉強中です。 勉強用にプログラムを組んでるのですが、構造体メンバに文字列を代入し出力する関数で予想とは違う結果が出てしまいました。思いつく限りの方法は試しましたが、状況は変わりませんでした。 先に、予想した実行結果と実際の実行結果を載せます。 char型配列data[32]に入力文字列を代入し出力した時 ・予想した結果 入力: abcdefgh 出力: abcdefgh ・実際の結果 入力: abcdefgh 出力: abc 次にコードと実行結果を載せます。 上記の通り、与えられた文字をそのまま出力するだけのプログラムです。 質問投稿用にメンバの量は1つにしました。 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<malloc.h> #define MAX_DATA 32 struct memb{ char s[MAX_DATA]; }k; void input_c(char *data){ data = (char *)malloc( sizeof(char)*32 ); printf("Size is %d\n",malloc_usable_size(data)); puts(">>> "); fgets(data,sizeof(data),stdin); sscanf(data,"%s",data); printf("DATA is %s\n",data); } int main(void){ input_c(k.s); printf("Inputted Data : %s\n",k.s); return 0; } -------------------------------------------- 実行結果 Size is 36 >>> abcdefgh DATA is abc Inputted Data : 以上です。 こういう状態になってしまう原因がどこにあるのか、何がそうさせているのかについて、 どうかご教授のほど宜しくお願い致します。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- Wr5
- ベストアンサー率53% (2173/4061)
>xを0で初期化 >xをパラメータとしてinput関数に渡す >5を入力 >ここでスタックには0がプッシュされたままで5がプッシュされる 実際に動かしてみた方がわかると思いますが……。 スタックがどうとかはこの場合関係ないです。 ローカル変数の値がどうなるか?です。 質問に掲示されたヤツだと…ポインタ使うのでそれぞれ下記のようにしてみてはどうですかね? input_c(k.s); の前に printf("k.s Address 0x%p\n", k.s); でk.sのアドレスを表示してみる。 data = (char *)malloc( sizeof(char)*32 ); の前後で printf("data Address 0x%p\n", data); でdataの指す先がどう変化するか確認する。 sizeof()がおかしいのは既に指摘されてます。 # 配列のポインタを引数にして関数コールしてもコールされた側ではその配列のサイズを知る手段がありません。 # 引数でサイズも渡す。というのがよくある方法です。 >sscanf(data,"%s",data); 取り出し元と書き出し先が同一領域で問題ないのか? については確認が必要かも知れません。 まぁ、仮に大丈夫だったとしても上記の処理では意味がありませんが。(ホワイトスペースで読み取りが終わる…かな?) ちなみに…input_c()の中でメモリリーク起きてます。 # malloc()で取得したヒープはいつ解放はてます? # 答え:プロセスが終了した時にOSが回収する。 # じゃあ、プロセスが終了しない場合はどうなるでしょうかね。
- TooManyBugs
- ベストアンサー率27% (1472/5321)
sizeof(data)がおかしい。 dataはmallocしたバッファへのポインタであってバッファそのものではないからsizeof(data)はバッファ長ではなくポインタのサイズ。 このシステムでは32ビットだったので4が返ってきたのだろう。 よってfgets(data,sizeof(data),stdin);では 'a','b','c',0x00が入る。
- Tacosan
- ベストアンサー率23% (3656/15482)
すみません, #1 の最後の行はゴミなので無視してください. ちなみに「質問のプログラムではポインタを渡しているので #1 のプログラムとは違う」という指摘は却下.
お礼
一部打ち間違えたまま投稿してしまいました すみません 訂正します xを0で初期化 xをパラメータとしてinput関数に渡す 5を入力 ここでスタックには0がプッシュされたままで5がプッシュされる input関数で5を出力 main関数で5を出力 (ここまででスタックから5がポップされる) 最後に残った0がポップされ出力される 以上訂正です。
補足
わかりそうでわかりませんが・・・ 5を入力した時の実行結果 5 5 0 xを0で初期化 パラメータとして渡す5 スタックには0がプッシュされたままで5がプッシュされる input関数で5を出力 main関数で5を出力 (ここまででスタックから5がポップされる) 最後に残った0がポップされ出力される ということでしょうか・・・ これが正しいとした上での質問ですが、これはprintf関数によるものですか? スタックだのヒープだのよくわからないんです… もしご存知であれば参考書やホームページ等を教えていただけますか?
- Tacosan
- ベストアンサー率23% (3656/15482)
#include <stdio.h> void input(int x) { scanf("%d", &x); printf("%d\n", x); } int main() { int x = 0; input(x); printf("%d\n", x); return 0; } というプログラムは, どう動くでしょうか? printf("
お礼
>dataはmallocしたバッファへのポインタであってバッファそのものではないからsizeof(data)はバッファ長ではなくポインタのサイズ。 全くその通りです・・・ありがとうございました!!