質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.01%

構造体を動的に確保する意味

受付中

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,805

FumiakiNakao

score 178

基礎的な質問で申し訳ありませんが皆さんのお力をお借りしたいです

学校の授業で以下のようなコードを組みました
(2分探索木についてのコードですが、内容そのものは質問とは
関係ありません)

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

typedef struct bst_node{
    int value;
    struct bst_node *left;
    struct bst_node *right;
} NODE;

NODE *root;


NODE *create_node(int d){
    NODE *p;

    p=malloc(sizeof(NODE));
    p->value=d;

    return p;
}

void insert_bst(int d){
     NODE *p;

     if(root==NULL){
         root=create_node(d);
         return;
     }

     p=root;
     while(1){
         if(p->value==d)return ;

         if(p->value>d){
             if(p->left==NULL){
                 p->left=create_node(d);
                 return;
             }else{
                 p=p->left;
             }
          }else {
                 if(p->right==NULL){
                     p->right=create_node(d);
                     return;
                 }else{
                     p=p->right;
                 }
             }
         }
}



void preorder(NODE *node){
    if(node==NULL) return;
    printf("%d->",node->value);
    preorder(node->left);
    preorder(node->right);
}

void inorder(NODE *node){
    if(node==NULL)return;
    preorder(node->left);
    printf("%d->",node->value);
    preorder(node->right);

}
void pastorder(NODE *node){

    if(node==NULL)return;
    pastorder(node->left);
    pastorder(node->right);
    printf("%d->",node->value);
}

int max_bst(){
    if(root==NULL){
        return -1;
    }
   NODE *p=malloc(sizeof(NODE));
   NODE *p=root;
    while(p->right!=NULL){
        p=p->right;
    }

    return p->value;
}


int main(){
    int i;
    int a[7]={17,24,4,9,11,2,23};

    for(i=0;i<7;i++){
        insert_bst(a[i]);
    }

    printf("preorder");
    preorder(root);
    printf("\ninorder");
    inorder(root);
    printf("\npastorder");
    pastorder(root);

    printf("\n Max value of BST is %d\n",max_bst());
}

ここで気になったのはところどころで、構造体のポインタを宣言したあとに、領域を動的に
確保していることです

(例えばcreate_node関数内におけるポインタp)

今までの私のイメージでは、動的確保は例えば配列の要素数分の領域を跡付けで定義するように
前もってわかっていない大きさの領域を後から確保する場合に使うものでした

ところが今回の場合、(私のイメージでは)確保する領域は構造体1つ分で前もってわかって
いるように思えます

このような場合に動的確保を行わなければいけないのはなぜでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+5

こんにちは。

確保する領域は構造体1つ分で前もってわかっているように思えます

create_node()関数内では1つしか生成していませんが、確保した領域へのポインタを戻り値で返却し、create_node関数の呼出し側でそのポインタを保持するようまた別のNODE構造体のleftやrightへ設定しています。
つまり、NODE構造体はプログラム全体では複数保持されており、その数は配列aの要素数で決まります。

今回は配列aのサイズは固定ですが、配列aをmalloc等で動的に確保することで可変にすることができますので、プログラムの構造的には、NODE構造体のインスタンスの数を可変にできるようになっています。
従って、malloc等を用いて動的に確保する必要があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+3

ところが今回の場合、(私のイメージでは)確保する領域は構造体1つ分で前もってわかって 
いるように思えます

ここの観点がずれていると思います。
一回に確保するのはあくまでも構造体1つ分ですが、これをノード数分必要です。
このノード数が固定でわかっているのであれば構造体を配列で用意しても良いのでしょうが、ノード数が可変数でも対応できるように動的に確保していることになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

NODE *create_node(int d){
    NODE n;
    /* 処理 */
    NODE *p = &n;
    return p;
}

では何がマズイのかということですね。

こう書くと、nの生存期間(=メモリ上にデータが有ることが保証される期間)は
create_node内のみです。

p1 = create_node(1);

などと書いても、データが残っていることが保証されないアドレスが帰ってきます。


NODE create_node(int d){
    NODE n;
    /* 処理 */
    return n;
}

こう書いた場合は、nの生存期間(=メモリ上にデータが有ることが保証される期間)は
create_node内のみですが、返すときにコピーするので、動作に問題ありません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る