• 締切済み

[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 : 以上です。 こういう状態になってしまう原因がどこにあるのか、何がそうさせているのかについて、 どうかご教授のほど宜しくお願い致します。

みんなの回答

  • Wr5
  • ベストアンサー率53% (2173/4061)
回答No.4

>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が回収する。 #    じゃあ、プロセスが終了しない場合はどうなるでしょうかね。

回答No.3

sizeof(data)がおかしい。 dataはmallocしたバッファへのポインタであってバッファそのものではないからsizeof(data)はバッファ長ではなくポインタのサイズ。 このシステムでは32ビットだったので4が返ってきたのだろう。 よってfgets(data,sizeof(data),stdin);では 'a','b','c',0x00が入る。

UNM_VHMT
質問者

お礼

>dataはmallocしたバッファへのポインタであってバッファそのものではないからsizeof(data)はバッファ長ではなくポインタのサイズ。 全くその通りです・・・ありがとうございました!!

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

すみません, #1 の最後の行はゴミなので無視してください. ちなみに「質問のプログラムではポインタを渡しているので #1 のプログラムとは違う」という指摘は却下.

UNM_VHMT
質問者

お礼

一部打ち間違えたまま投稿してしまいました すみません 訂正します xを0で初期化 xをパラメータとしてinput関数に渡す 5を入力 ここでスタックには0がプッシュされたままで5がプッシュされる input関数で5を出力 main関数で5を出力 (ここまででスタックから5がポップされる) 最後に残った0がポップされ出力される 以上訂正です。

UNM_VHMT
質問者

補足

わかりそうでわかりませんが・・・ 5を入力した時の実行結果 5 5 0 xを0で初期化 パラメータとして渡す5 スタックには0がプッシュされたままで5がプッシュされる input関数で5を出力 main関数で5を出力 (ここまででスタックから5がポップされる) 最後に残った0がポップされ出力される ということでしょうか・・・ これが正しいとした上での質問ですが、これはprintf関数によるものですか? スタックだのヒープだのよくわからないんです… もしご存知であれば参考書やホームページ等を教えていただけますか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

#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("

関連するQ&A