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

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

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

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

Q&A

解決済

3回答

417閲覧

線形リストで場合分けなしの挿入をダブルポインタで作成する方法がわかりませんver2.0

apeirogon0813

総合スコア117

C

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

0グッド

0クリップ

投稿2019/03/23 14:30

編集2019/03/24 13:29

前提・実現したいこと

線形リストの昇順にソートされる挿入関数を以下の図のように作成する上で、関数insert2はリストの先頭に挿入する場合分けをなくすためにダブルポインタを用いて作成するのですが、以下の空欄のお〜きに入る式がわかりません。
イメージ説明

該当のソースコード

C

1typedef struct list { 2 int data; 3 struct list *next; 4} list 5 6list * list_alloc(int data) { 7 list *p = malloc(sizeof(list)); 8 p->data = data; 9 p->next = NULL; 10 return p; 11} 12 13void insert2(list ** head_p, int data) { 14 list * new = list_alloc(data); 15 list **p = head_p; 16 while(&&) { 17 p =; //次のnextメンバーを指す 18 } 19 new->next = *p; 20 *p = new; 21} 22int main() { 23 list *head = NULL; 24 insert2(&head,100); 25 insert2(&head,50); 26 insert2(&head,20); 27}

試したこと

![イメージ説明]
間接メンバー"->"は選択演算*、アドレス演算&より優先順位が高いことを考慮して,
"お"、"か"はそれぞれ
**while(p != NULL && data < (p)->data)
で、"き"は
*p = &(p)->next;
であると思うのですが、これは
**p = p
p = * *p
と表記することも等しいと思うのですかどうなんでしょうか。

追記: int a = 0; int *p = &a; の場合

イメージ説明

struct list *p; p = malloc(st....
イメージ説明

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

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

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

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

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

jimbe

2019/03/23 17:12

p** とは何でしょう.
apeirogon0813

2019/03/24 10:44 編集

すみません間違ってました。正しくは**pです。
guest

回答3

0

ベストアンサー

間接メンバー"->"は選択演算*、アドレス演算&より優先順位が高いことを考慮して,

"お"、"か"はそれぞれ
while(*p != NULL && data < (*p)->data)
で、"き"は
p = &(*p)->next;
であると思うのですが、

昇順のリストを作成するのであれば、"か"の符号が逆だと思うのですが。
"お" と "き" は合っていると思います。

これは

p = p**
と表記することも等しいと思うのですかどうなんでしょうか。

前の質問からして、p = p**p = **pであろうかと思いますが、**pの型はlistです。list **であるpには代入できませんね。
ご自身で書かれた図のように、pは最初headを指し示しています。p = &(*p)->next;により、*pの指し示す(=headの指し示す)ノードのメンバーnextへのポインターがpに代入されます。それにより、次々とリストを辿ることが出来るようになります。

投稿2019/03/24 01:04

Bull

総合スコア986

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

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

apeirogon0813

2019/03/24 10:41

すみませんおっしゃる通り**pです。では**pまたは*headはどこを示しているのでしょうか?
Bull

2019/03/24 12:24

回答にも書きましたが、**p (=*head) の型は list です。ですのでどこも指してませんよ。構造体そのものです。 例えば、 int a; int *ptr = &a; であるとき、ptr は a を指しますが、*ptr は何でしょうか? a = 0; とするのと *ptr = 0; とでは、おなじことですよね。 ポインタのポインタと考えるとややこしいですが、p が指しているのが list * 型の変数なだけで、本質的には単一のポインタと何ら変わらないですよ。 また、このようなリスト構造の場合、ポインタの指し示しているのが変数や配列ではなく、malloc 関数で動的に領域(オブジェクト)なので、イメージしづらいのかもしれません。 malloc 関数が名前のない list 型の構造体を必要なだけ確保してくれると考えると、多少はイメージできるでしょうか。
apeirogon0813

2019/03/24 13:55 編集

追記に画像を添付しました。おっしゃっていただいたint型のポインタの場合*ptrはポインタ先の値(int)を示すのはわかりますが、struct型の場合、構造体なので中に複数変数があり, 追記の画像のような場合, *pはポインタ先のlistのどこの値?を指しているのかやはりわかりません。
Bull

2019/03/25 00:12

追記した図についてお答えします。 ポインターの値(≒アドレス)としては p と &(p->data) は同じです。 しかし data は int 型なので混同しない方がいいですね。ポインターの指している先の型が違います。p が指し示しているのはあくまでも list 型のオブジェクトなんです。 *p の型は list なので、p->data と (*p).data は同じです。 図で言いますと *p と b は同じものです。 あくまでも私見ですが、ポインターを理解しようとするとき、オブジェクトを意識するといいじゃないかと。 オブジェクトと言うと小難しく感じますが、ようは変数とか配列とか malloc で確保したメモリー領域などのことです。 "~型へのポインタ" などと言いますが、正確には "~型のオブジェクトへのポインタ"と言うのが正確なんじゃないかと私は考えています。 くどいようですがポインタの指し示している先は何らかの型のオブジェクトです。オブジェクトを抜きにポインタを論じても意味がないと思っています。 先のコメントで唐突に int 型のポインタを持出しましたが、これは int 型のポインタでも list 型のポインタでも本質的には同じで、ポインタが~型のオブジェクトを指し示していることを強調したかったからです。 list *p = malloc(sizeof(list)); と list b; list *p = &b; では、オブジェクトの寿命とか格納されるエリアとかいろいろ違いはありますが、p が list 型のオブジェクトを指し示していることには、違いがありません。
apeirogon0813

2019/03/25 05:34

ご返信ありがとうございます。 なるほど、型に注目すると少し理解できたような気がします。オブジェクトについても調べてみます。 ありがとうございました。
guest

0

と思うのですかどうなんでしょうか。

そう思うのでしたらやってみたらどうでしょうか


供養

c

1#include <stdio.h> 2#include <stdlib.h> 3 4struct list; 5 6typedef struct list { 7 int data; 8 struct list *next; 9} list; 10 11list* list_alloc(int data) { 12 list *p = malloc(sizeof(list)); 13 p->data = data; 14 p->next = NULL; 15 printf("new list[%p] => %d, %p\n", p, data, &(p->next)); 16 return p; 17} 18 19void insert2(list ** head_p, int data) { 20 puts("-------------"); 21 list * new = list_alloc(data); 22 list **p = head_p; 23 printf("head_p = %p, *head_p = %p\n", head_p, *head_p); 24 while(&&) { 25 printf("p = %p, *p = %p, ", p, *p); 26 printf("next_p = %p, *next_p = %p\n",, *); 27 // もしもタイムアウトになったならば以下のコメントアウトを外す 28 // return; 29 p =; // 次のnextメンバーを指す 30 } 31 new->next = *p; 32 *p = new; 33} 34int main() { 35 list *head = NULL; 36 insert2(&head,100); 37 insert2(&head,50); 38 insert2(&head,20); 39}

お、か、きを埋めてwandboxなりpaiza.ioなり
で実行してみてはどうでしょう。
(一番いいのはMSVCでデバッグ実行ですが)

投稿2019/03/24 01:48

編集2019/03/25 09:52
asm

総合スコア15147

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

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

0

p = &(*p)->next;

p = &((*p)->next);
と書き換えるとわかると思いますが、nextのアドレスです

投稿2019/03/23 22:17

y_waiwai

総合スコア87774

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

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

apeirogon0813

2019/03/24 10:45

おっしゃる通りnextのアドレスでした。では, &**pはnextのアドレスを示してはいないのでしょうか。
y_waiwai

2019/03/24 11:03

示してませんね
apeirogon0813

2019/03/24 12:01

**pはどこをしめしているのでしょうか?
y_waiwai

2019/03/24 12:13

list を示しますな
apeirogon0813

2019/03/24 13:43

つまり1つのノードのアドレスを示しているのでしょうか?
episteme

2019/03/24 18:25

**p はlistそのもの。どこかのアドレスを示してはいない。
apeirogon0813

2019/03/25 05:35

おっしゃる通りでした。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問