malloc realloc ポインタの参照渡しについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ruce

malloc realloc ポインタの参照渡しについて

#1

投稿記事 by ruce » 15年前

はじめまして、C言語の勉強をしている者です。
ポインタの参照渡しを行い、2日ほど足踏みしている状態で
もうどうにもわからないので、質問します。

以下にサンプルコードを書きます。
===================================================
1. 普通に動くもの
===================================================

---------------------------------------------------
main
[概要] aの配列を hoge関数に参照渡しを行い
       aの配列に値を代入する。
       要素は「5」個とする。
---------------------------------------------------
int main(void) {
  int a[5];

  hoge(a);
  return 0;
}

---------------------------------------------------
hoge
---------------------------------------------------
void hoge(int *a) {
  int i;

  for (i = 0; i < 5; i++) {
    a = i;
  }
}

/// ends


===================================================
2. 質問(動かないもの)
===================================================

---------------------------------------------------
main
[概要] aの配列を hoge関数に参照渡しを行い
       aの配列に値を代入する。
       要素は決まっていない。
---------------------------------------------------
int main(void) {
  int a[1];

  hoge(a);
  return 0;
}


---------------------------------------------------
hoge
---------------------------------------------------
void hoge(int *a) {
  int i;
  int *buf;
  int total = 0;

  // 要素生成
  a = (int *)malloc(sizeof(int) * 1);

  // 999 になるまで繰り返す
  for (i = 0; total <= 999; i++) {

    // 実際は「i」ではなく、キーボードからの入力値になります。
    a = i

    // 合計に加算
    total += tensuu;
    if (total <= 999) {
      // 要素生成
      buf = (int *)realloc(a,sizeof(int) * i + 2);
      if (buf == NULL) {
        exit(0);
      }
      a = buf;
    }
  }
}

/// ends

かなり醜くて申し訳ありません。。。

参照渡しを行い、値を設定し戻してくれるものだと思っていたのですが
「malloc」, 「realloc」を使用すると、どうもうまくいきません。

使い方がダメなのでしょうか。。
すみません。どなたか。。。どなたかご教授いただけないでしょうか。 画像

フリオ

Re:malloc realloc ポインタの参照渡しについて

#2

投稿記事 by フリオ » 15年前

 
 main の int a[1]; はint型の配列として宣言されているので、
a の値を変更できません。int *a; としましょう。
 
 
 参照渡し(ポインタの値渡し)は、値を変更したい変数へのポインタを渡します。

この場合は、int型へのポインタ型の変数 a の値を変更したいので、
a へのポインタ、つまりint型へのポインタ型へのポインタ型を渡さなければなりません。
したがって、void hoge(int *a) ではなく void hoge(int **a) です。
 
 realloc だけでなく、malloc のエラーチェックもすべきです。
 tensuuは a の間違いでしょうか。
 
画像

non

Re:malloc realloc ポインタの参照渡しについて

#3

投稿記事 by non » 15年前

>buf = (int *)realloc(a,sizeof(int) * i + 2);
最後の+2は、何でしょう?

ruce

Re:malloc realloc ポインタの参照渡しについて

#4

投稿記事 by ruce » 15年前

>> フリオさん
ありがとうございます!

> realloc だけでなく、malloc のエラーチェックもすべきです。
すみません。そうします!

> tensuuは a の間違いでしょうか。
間違いです。すみません。。。

ポインタのポインタを引数にして
早速昼からガリガリやっているのです
が、できません。。。なぜ

以下にサンプルコードを書きます。(main)は省きます。
==========================================
hoge
[変更点]
・ 引数を「int *」 → 「int **」に変更。
・ malloc, realloc のキャストを
「int *」 → 「int **」に変更。
==========================================
void hoge(int **a) {
  int i;
  int total = 0;

  a = (int **)malloc(sizeof(int) * 1);
  if (a == NULL) {
    exit(0);
  }

  for (i = 0; total <= 999; i++) {
    // ここでエラー
    a = i
    total += a;
    if (total <= 999) {
      a = (int **)realloc(tensuu,sizeof(int) * i+2);
      if (a == NULL) {
        free(a);
        exit(0)
      }
    }
  }
}


ずばり聞きます。
何を勉強すれば、ここの関数を綺麗に通すことができますか!
もう3日もこの問題に。。。悲しいです。
どうかもう少しだけお付き合いをお願いします。。。

>> nonさん

> 最後の+2は、何でしょう?
最初に malloc で要素を「1」取得し、
次に「2, 3, 4 …」と前の値を
保持したまま要素を取得したかったから「i + 2」にしました!

…あれ?もしかしておかしいですか。。。?

box

Re:malloc realloc ポインタの参照渡しについて

#5

投稿記事 by box » 15年前

せめて、コンパイルエラーくらいは自分で除去しましょう。
tensuuという未定義変数を使っていたり、文末を示すセミコロンがなかったり…。


> // ここでエラー

何というエラーですか?


現時点でのソースを「そっくりそのまま」さらしてみてはどうでしょう。
main関数も、省略せずに。 画像

non

Re:malloc realloc ポインタの参照渡しについて

#6

投稿記事 by non » 15年前

>> 最後の+2は、何でしょう?
>最初に malloc で要素を「1」取得し、
>次に「2, 3, 4 …」と前の値を
>保持したまま要素を取得したかったから「i + 2」にしました!

ということは、intは2バイトだと決め打ちをしたことになりますね。
何のために,sizeof(int)を使っているのか意味がなくなります。

non

Re:malloc realloc ポインタの参照渡しについて

#7

投稿記事 by non » 15年前

>a = (int **)realloc(tensuu,sizeof(int) * i+2);
ああ、もしかしたら、

a = (int **)realloc(tensuu,sizeof(int) * (i+2));
括弧がないのか。


ruce

Re:malloc realloc ポインタの参照渡しについて

#9

投稿記事 by ruce » 15年前

> nonさん
と・・とれてる・・・!?
とれてる!
な。。。なんで。。。!?

できました…とうとう!ありがとうございます!

で、でも中身が見たい・・・どうなっているんだろう。
VC++ 2008 で配列の中身をずらーっとみれる方法がないものか。。。。

ありがとうございます!


> boxさん
ソースコードをさらします!
変なところがあればどうかご教授をお願い致します。。。
---------------------------------------------------
main
[問題] 点数を 999 になるまで入力させる。

今回、動的に配列を拡張させる方法を学びたく
malloc, realloc を使用しました。
結果、3日も。。。
---------------------------------------------------
int main(void) {
  int *tensuu = 0;
  int tensuuLen;

  tensuuLen = pGetTensuu(&tensuu);
  return 0;
}

---------------------------------------------------
pGetTensuu
---------------------------------------------------
int pGetTensuu(int **tensuu) {
  int i;
  int total = 0;

    // 指定した引数の数値分
    // 要素を取得し、アドレスを戻す関数
  *tensuu = PMallocIntegerArgument(1);
  for (i = 0; total <= 999; i++) {
    // 指定した文言を表示し
    // 指定した長さ以内の   (TENSUU_LENGTH : 3)
    // 指定した最大値から   (TENSUU_MAX    : 999)
    // 指定した最小値までの (TENSUU_MIN    : 0)
  // 値を入力させ、戻す関数
    *(*tensuu + i) = PGetInteger("点数を入力してください", TENSUU_LENGTH, TENSUU_MAX, TENSUU_MIN);
    total += *(*tensuu + i);
    if (total <= 999) {
      // 指定した前ポインタの情報を保持し
      // 指定した要素数分
      // 要素を取得し、アドレスを戻す関数
      *tensuu = PReallocIntegerArgument(*tensuu, (i + 2));
    }
  }
  return i;
}
すみません。汚いかもしれないですが、ご指摘を…!


====================================================
たびたびすみません。
実は別の問題にも手を出していまして…

かなり虫のいい話なんですが
そちらの質問も少しだけ、少しだけヒントをいただければと

内容は以下の通りです。(自分で考えた内容, 方法なのですが…)
・ ファイルの中身を二次元配列に格納する

このとき、二次元配列を malloc, realloc で動的に
(ファイルの行数分の要素, ファイルの一行の文字列分の要素)
要素を取得できないものかと。。。

すみません。もう少しだけお付き合いお願いいただければ…!

甘えるな!ということで無理であれば放置していただいてOKです。。!
もしどなたか見ていただければソースコードをさらします。
====================================================

non

Re:malloc realloc ポインタの参照渡しについて

#10

投稿記事 by non » 15年前

>このとき、二次元配列を malloc, realloc で動的に
(ファイルの行数分の要素, ファイルの一行の文字列分の要素)
要素を取得できないものかと。。。

もちろんできます。
ただ、2次元配列の必要があるのかよく考えてください。
1次元配列にする
ポインタ配列にする
構造体にする
など・・・

前のプログラムも勉強としては、これでいいのですが、
確保したメモリのアドレスをreturnした方が簡単だと思う。
ソースに問題がないかどうかは、自作関数部分も添付してくれなきゃわからない。

閉鎖

“C言語何でも質問掲示板” へ戻る