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

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

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

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

Q&A

解決済

2回答

770閲覧

c言語 参照渡しの&がある場合とない場合の違い (構造体)

Yoshikatsu

総合スコア9

C

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

0グッド

0クリップ

投稿2023/01/24 06:54

編集2023/01/24 07:02

前提

c言語で双方向循環リストを実装しながら疑問に感じたことがある。それは

#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct s_stack { int num; struct s_stack *prev; struct s_stack *next; } t_stack; void change_content(t_stack *stack) { t_stack *tmp; tmp = stack; tmp->num = 100; } int main(void) { t_stack *stack; stack = malloc(sizeof(t_stack) * 1); stack->num = 0; stack->prev = NULL; stack->next = NULL; change_content(stack); printf("%d", stack->num); return 0; }

この場合はchange_contentの引数に'stack'と入れることで参照渡しができ、値が変わっておりますが、この双方向循環リストに値を入れていってソートする場合などは'&stack'と引数に渡している人がいます。どちらも値を変えるという点は同じであるのに、使い分けている人がいるのはなぜでしょうか?どういう違いがあるのでしょうか?

void change_content(t_stack **stack); change_content(&stack);

プロトタイプ宣言も**stackとダブルポインタにしています。どういう違いがあるのでしょうか?

つまり 質問は

参照渡しをするとき、&をつける時と、つけない時の違いは何ですか? リストを操作する上での違いはありますか?

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

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

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

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

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

fana

2023/01/24 08:29

* や & に関しては純粋に文法の話なので,まずは復習されるのが早いかと. 「文法面の把握には問題がないが,特定の実装の意味みたいなところの把握等が問題だ」ということであれば > '&stack'と引数に渡している人がいます とかじゃなく,実例のコードを具体的に示さないと話ができないのでは.
guest

回答2

0

ベストアンサー

もしも

C

1void change_content(t_stack stack) //※引数がポインタではない 2{ 3 stack.num = 7777; //いじくる? 4}

とかしたら,引数 stack の内容を関数内でいじくっても呼び出し元が渡した物に影響が出ない.
それだと困るから ,あなたは引数の型を t_stack* なるポインタ型にしているのですよね?

ダブルポインタでも話は同じでしょう.
引数が普通にポインタの場合:

C

1void SomeFunc( t_stack* p ) 2{ 3 p = NULL; //いじくる? 4}

に,ポインタ型変数を引数として渡した場合,呼び出し元が渡したポインタ型引数は影響を受けませんよね.
誰かがダブルポインタを使っている理由は, それだと困るから(すなわち,呼び出し側にあるポインタ型変数の値自体を書き換えたいから) でしょう.

投稿2023/01/24 08:50

fana

総合スコア11658

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

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

fana

2023/01/24 08:54 編集

質問文内に例として「ソート」が挙げられていますが,そのソート処理をする関数に「リストの先頭ノードを挿すポインタ型変数」を渡すのだとしたらどうでしょうか? ソート処理の結果として リストの先頭 が変わり得るわけですが,それをどうやって呼び出し元に反映させるのでしょう? その方法として「引数をダブルポインタにする」ことを選んだ人がいた,というだけのことではないでしょうか.
Yoshikatsu

2023/01/24 09:06

とてもわかりやすい説明ありがとうございます。なるほどですね。リストを操作する上ではダブルポインタでリストの先頭ノードを挿すポインタ型変数だと反映されないのですね。仕組みもとてもわかりやすかったです。ありがとうございます。
fana

2023/01/24 09:31

混乱した際には,よくある(?)絵でも描いて思考を整理すれば良いかもしれません. 「アドレス空間のどこかに malloc された(s_stackのサイズ分の)領域があって,そこを指し示す値を持つポインタ型の変数があって…」っていうやつ. ダブルポインタの話も 「ポインタ型変数も変数なのだから当然そいつ用の領域というのもあって,さらにダブルポインタ型の変数もあってそいつの値というのはポインタ型変数の場所を際していて…」とかいう感じで.
guest

0

&と言うのは参照渡しではないです。
単にアドレスを取ってるだけです

投稿2023/01/24 07:23

y_waiwai

総合スコア87774

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

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

Yoshikatsu

2023/01/24 07:34

つまり、参照わたしが行われる場合はその引数がアドレスか値かという違いということでしょうか
Yoshikatsu

2023/01/24 07:35

t_stack *stack; の値を変える上で stackでも変わるし &stackでも変わるということはわかりました。では、&stack stackの違いはなんでしょうか?
Yoshikatsu

2023/01/24 07:37

なんとなくの理解ですが、stackを入れる時はノードの先頭ポインタが渡され、&stackを入れる際はリスト構造自体のポインタが渡されるという認識ですが、間違いないですか?
y_waiwai

2023/01/24 08:01

いや、そもそもC言語には参照渡しという概念がありません &という演算子は、アドレスをとってくる演算子です stack という変数があれば、&stackというのは、その変数のアドレスを返します stack というポインタ変数があるなら、&stackというのは、ポインタ変数のアドレスを返します そこらへん、きちんと理解しときましょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問