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

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

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

4回答

1208閲覧

自己参照型構造体の配列

Egg-Man

総合スコア38

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/11/01 14:32

編集2021/11/01 16:52

###自己参照型構造体の配列は可能か?

自身と同じ型を持つ構造体同士を
繋ぎ合わせるために必要なのが
自己参照型構造体ですが、
それを宣言する際についての質問です。

該当のソースコード

typedef struct node { int ID; struct node*Link[ ]; }NODE;

????上記のように、自己参照型構造体を**「配列」**として宣言するのは規格に反するのでしょうか?

試したこと

とりあえず上記のように宣言した上で
作業を進め、コンパイルを実行すると何も起きずそのままプログラムが終了します。(エラーメッセージなし)

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

int32_t

2021/11/01 15:36

コンパイルエラーの場合はエラーメッセージを必ず書いてください。
Egg-Man

2021/11/01 16:43

承知致しました。
guest

回答4

0

[]の中に配列の要素数を書けば問題ないです。

構造体の末尾のメンバーの場合は、要素数を書かない[]のままでも文法的にはOKですが、可変配列メンバーとなり、NODEへのポインターを宣言してmallocで必要サイズを割り当てるという使い方になります。

投稿2021/11/01 16:05

otn

総合スコア85901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Egg-Man

2021/11/01 16:25

ご回答ありがとうございます。 「構造体の末尾のメンバーの場合は、要素数を書かない[]のままでも文法的にはOK」 ↑については、 初めて知ることができました。 構造体、奥が深いですね( ゚д゚)
guest

0

要素数不定(0)の配列が構造体メンバの最後にひとつだけであれば(ちゃんと書けば)無問題。

C

1#include <stdio.h> 2#include <stdlib.h> 3 4typedef struct node { 5 int ID; 6 int size; 7 struct node* Link[0]; 8} NODE; 9 10NODE* allocate(int id, int size) { 11 NODE* ptr = (NODE*)malloc(sizeof(NODE)+sizeof(NODE*)*size); 12 if ( ptr ) { 13 ptr->ID = id; 14 ptr->size = size; 15 for ( int i = 0; i < size; ++i ) ptr->Link[i] = NULL; 16 } 17 return ptr; 18} 19 20void print(const NODE* node) { 21 printf("ID:%d Link:", node->ID); 22 for ( int i = 0; i < node->size; ++i ) { 23 printf("%p ", node->Link[i]); 24 } 25 printf("\n"); 26} 27 28int main() { 29 NODE* p = allocate(123, 4); 30 print(p); 31 free(p); 32 return 0; 33}

投稿2021/11/01 16:02

編集2021/11/01 16:03
episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Egg-Man

2021/11/01 16:30

コードまで丁寧に書いて頂き、 有り難うございます。 NODE* ptr = (NODE*)malloc(sizeof(NODE)+sizeof(NODE*)*size); ????このように、sizeof演算子を連続で使う方法は思いも及びませんでした。 驚きと発見で感無量です( ´ ▽ ` )
episteme

2021/11/01 21:08

要は構造体の総サイズを求めてるだけですから。
Egg-Man

2021/11/04 15:10

すいません、少し腑に落ちない点がありまして.... 例えば、 NODE* ptr = (NODE*)malloc(sizeof(NODE)+sizeof(NODE*)*3); とした場合は ptr->Link[0], ptr->Link[1], ptr->Link[2], の3つなのか、それとも ptr->Link[0]->Link[0], ptr->Link[0]->Link[1], ptr->Link[0]->Link[2], のようなイメージでいいのか、どちらが正しい認識なのでしょうか?
episteme

2021/11/04 17:17

typedef struct node { int ID; int size; struct node* Link[3]; } NODE; と同義です。
guest

0

ベストアンサー

配列サイズが固定ではないなら、構造体の定義ではサイズが決まらないといけないので、0サイズの配列として定義するか、ポインタの配列を動的に確保します。

配列サイズのメンバーを足す必要もあるでしょうね。

c

1typedef struct node { 2 int ID; 3 struct node* Link[0]; 4} NODE; 5 6// 配列がN要素のときの確保 7NODE* p = (NODE*)malloc(sizeof(NODE) + sizeof(NODE*) * N);

c

1typedef struct node { 2 int ID; 3 struct node** Link; 4} NODE; 5 6// 配列がN要素のときの確保 7NODE* p = (NODE*)malloc(sizeof(NODE)); 8p->Link = (NODE**)malloc(sizeof(NODE*) * N);

投稿2021/11/01 15:36

編集2021/11/01 16:10
int32_t

総合スコア21695

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Egg-Man

2021/11/01 15:56

なるほどです。 凄く分かりやすく、有難うございます。 ちなみになんですが、 1つ目の回答における malloc(sizeof(NODE) + sizeof(NODE*) * N); の箇所を初めて見ました。 この場合の「sizeof(NODE*)*N」 の部分は、構造体メンバ変数のint型ID のサイズは確保しない、との認識で正しいでしょうか?
int32_t

2021/11/01 16:00

そうですね。IDは前半の sizeof(NODE) に含まれていて、後半の sizeof(NODE*) * N は Link のぶんだけです。
Egg-Man

2021/11/01 16:21

そういうメモリの確保法があったなんて凄い!!感動です。 有難うございます。
Egg-Man

2021/11/04 15:13

すいません、まだ少し腑に落ちない点がありまして.... 例えば、 NODE* p = (NODE*)malloc(sizeof(NODE)+sizeof(NODE*)*3); とした場合、 p->Link[0], p->Link[1], p->Link[2], の3つなのか、それとも p->Link[0]->Link[0], p->Link[0]->Link[1], p->Link[0]->Link[2], のようなイメージでいいのか、 どちらが正しい認識なのでしょうか?
guest

0

自己回答ではなく、回答予想になっていたため削除しました。

投稿2021/11/01 15:29

編集2021/11/01 16:48
Egg-Man

総合スコア38

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

int32_t

2021/11/01 15:37

これは回答ではないので、質問文に追記してください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問