←検索窓の楽しみ方
  ショッピングモール  掲示板ランキング


【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※返信付き投稿の削除は禁止!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら


 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板1こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.4005

メモリの動的確保について
投稿者---やぎ(2005/06/11 21:22:13)


2次元配列(として利用できる領域)を動的に確保するべく、以下のようなソースを書きましたが、コメントに書いたようなことになり、悩んでいます。

/*
    別の関数内で動的に確保した領域が使えない...
    なして?
    タブ幅は4
*/

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

void CreateMatrix(int**,int*,int*);

int main()
{
    int** buf;
    int col, row;
    int i, j;
    
    //動的に確保する

    CreateMatrix(buf, &row, &col);
    
    //確認(条件は真になり、プログラムは終了)

    if( NULL==buf ){
        fprintf(stderr, "ヌルポインタ\n");
        exit( 1 );
    }
    
    //もちろん、これ以下は実行されない。

    //以下でもbufを2次元行列として扱いたいのだが...

    
    //配列の内容を表示

    for(i=0;i<row;i++){
        for(j=0;j<col;j++){
            printf("%d ", buf[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    
    
    /* メモリ解放の処理(めんど臭いから、ここでは割愛) */
    
    return 0;
}

/*
    2次元配列(として利用可能な領域)を動的に確保する
*/
void CreateMatrix(int** buf, int* row, int* col)
{
    int i, j;
    
    //行数と列数を設定

    printf("row col > ");
    scanf("%d%d", row, col);
    
    //メモリを確保

    buf = (int**)malloc( (*row)*sizeof(int*) );
    for(i=0;i<(*row);i++){
        buf[i] = (int*)malloc( (*col)*sizeof(int) );
    }
    
    //適当に代入

    for(i=0;i<(*row);i++){
        for(j=0;j<(*col);j++){
            buf[i][j] = i+1;
        }
    }
    
    return;
}


CreateMatrix関数以外でbufがNULLになってしまうんです。
CreateMatrix関数以外でもbufを2次元配列として取り扱いたいのですが、どう修正したらよいのでしょうか?

変数のスコープとかそんな話が関係しているんでしょうか...。

稚拙なコードで恐縮ですが、指摘していただければ非常に嬉しく思います。
よろしくお願いします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:メモリの動的確保について 4006 iijima 2005/06/11 22:06:16
<子記事> Re:メモリの動的確保について 4008 Blue 2005/06/11 23:17:47


No.4006

Re:メモリの動的確保について
投稿者---iijima(2005/06/11 22:06:16)


関数の引数を通じて呼び出し元の変数の値を変更するには、引数としてその変数を指すポインタを関数に渡す、という基本に返ってCreateMatrix関数をよく見ると、、、

CreateMatrix関数は第1引数を通じて呼び出し元のbufの値を書き換える(関数内で確保したメモリ領域を指すポインタの値にする)ことを意図していると思われますが、掲げられたコードでは、bufを指すポインタを渡すようになっていない(bufの値が渡されている)ため、呼び出し元のbufの値を関数内で書き換えることができないのです。

次の関数が、呼び出し元の変数の値に影響を及ぼさないのと同じことです。
void f( int a ){ a = 1; }

CreateMatrix関数の場合、第1引数の型を「int型ポインタのポインタのポインタ」とし、呼び出し元のbufを指すポインタを渡してやらなければ、呼び出し元のbufの値を書き換えることはできません。

void CreateMatrix( int***, int*, int* );

当然、それに伴って関数定義も修正が必要です。

蛇足ですが、関数内で確保したメモリ領域を指すポインタの値を戻り値として返す方法もあります。

int** CreateMatrix( int*, int* );


この投稿にコメントする

削除パスワード

No.4008

Re:メモリの動的確保について
投稿者---Blue(2005/06/11 23:17:47)


わたしも、iijimaさんの
>蛇足ですが、関数内で確保したメモリ領域を指すポインタの値を戻り値として返す方法もあります。
>int** CreateMatrix( int*, int* );
をオススメします。

ちなみに DeleteMatrixみたいな領域開放のほうの関数は、
int*** にしなくてもmallocした領域が開放できます。

例)
void DeleteMatrix( int**, int, int );


ところで、こちらの方と同じ方でしょうか?(間違えならすいませんが)
http://cgi21.plala.or.jp/keny01/wforum/wforum.cgi?mode=allread&no=1734&page=0
あのあと続けて質問なされてもよかったのですけどね。
# 結構見ている人は同じなんですよね。



この投稿にコメントする

削除パスワード

No.4009

Re:メモリの動的確保について
投稿者---Blue(2005/06/11 23:26:03)


本題とずれますが、
>    int** buf;
>    if( NULL==buf ){
の処理がちょっと。。。

buf は初期化していませんので、ゴミが設定される可能性があります。
なので
int** buf = NULL;
と明示的に初期化しましょう。

それと、CreateMatrixで設定される場合 buf に NULL が設定されるのを
想定しているのならば、
CreateMatrix内の、
>    for(i=0;i<(*row);i++){
>        buf[i] = (int*)malloc( (*col)*sizeof(int) );
>    }
の処理のまえに if ( buf != NULL ) のような判定文を入れたほうがよいかと。
(malloc後のの戻り値のチェックをするようにしたほうがいい)



この投稿にコメントする

削除パスワード

No.4010

Re:メモリの動的確保について
投稿者---やぎ(2005/06/12 01:24:13)


iijimaさん、Blueさんありがとうございました。
ポインタが分かっていないことは自覚していましたが、ここでまた痛感しました。いくつも*がつくとこんがらがっちゃいますもん...。
精進しますッ。

>それと、CreateMatrixで設定される場合 buf に NULL が設定されるのを想定しているのならば...

あ、main関数のif文は最終的なコードから除外するつもりです。
if(NULL==buf)なんですが、「なんでmainでbufが使えんのや!」と思い、CreateMatrix関数の前後でbufが指すアドレスを実際に数回プログラム走らせて見てみたら、ずっとNULLだったので、何も考えずにその場限りに書いてしまったものです。
マズさは自覚していましたが、書き込む前に修正をすべきでしたね。


>ところで、こちらの方と同じ方でしょうか?(間違えならすいませんが)

ずばり、そうです。
むちゃくちゃ恥ずかしいです...。
(^^;

>あのあと続けて質問なされてもよかったのですけどね。

教えていただいたソースコードと、ほぼ同じソースコードを自分も書いていたので、あちらで書いたことがバグの原因ではないとわかり、その後ソースコードを見直して、こちらで質問した内容がバグに関わっていたと分かった次第です。
つづけて質問するのも、「少しは自分で考えろよなぁ...」と思われるかなと思い、なんだか気が引けてこちらで。

しかし、世界は狭いもんですね。

後半は掲示板の主旨から逸脱した書き込みで、すみません。



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧




掲示板提供:Real Integrity