🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

解決済

3回答

3307閲覧

C言語において関数内でグローバル変数の値を変える処理について

Sukabo

総合スコア31

C

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

0グッド

0クリップ

投稿2019/11/16 08:10

次の2つのコードについて、わからないことがあったので質問させていただきます。

一つ目のコードでsum変数を関数内で参照し、値を変えることができているのに、二つ目のコードで関数内でaとbの値を変えられないのはなぜでしょうか。

c

1int sum = 0; 2 3int add_point(int); 4 5int main(){ 6 int all_ point = 0; 7 all_point = add_point(10); /* all_point == 10*/ 8 all_point = add_point(20); /* all_point == 30*/ 9} 10 11int add_point(int x){ 12 sum += x; 13 return sum; 14}

c

1void swap(int, int); /* 数値を入れ替える(ことを目的とした)関数 */ 2 3int main(){ 4 int a = 5, b = 10; 5 swap(a, b); /*a == 5, b == 10 となり入れ替わっていない*/ 6} 7 8void swap(int x, int y){ 9 int tmp; 10 tmp = y; 11 y = x; 12 x = tmp; 13}

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

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

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

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

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

guest

回答3

0

投稿2019/11/16 08:18

cateye

総合スコア6851

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

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

LouiS0616

2019/11/16 08:32

ご提示のリンクの『参照渡し』とは全く違う機能としてC++に『参照渡し』が存在するので、C ⇒ C++ の順で学習する人にとっては誤解があるように思います。
cateye

2019/11/16 08:49 編集

参照渡し(Call by Reference)に感しては、“参照(アドレス)を渡す”と有りますが、 ret = sub( i, &j ); やint sub( int a, int *b )はCの構文と思われますが・・・ アドレス渡しw?・・・言葉の違いでしょうか?・・・どういうのかなぁ・・・
LouiS0616

2019/11/16 09:01 編集

C++の参照渡し(というか参照)は変数そのものを共有することができ、イメージとしてはエイリアスやシノニムに近いです。 Cのポインタ渡しはポインタを値渡ししているだけです。ただポインタのことを参照と呼ぶ人もいるので非常にややこしいです。参照値と呼べば語弊が生まれづらいのですが... 参照(値)『を』渡すのと、参照『で』渡すのと、その違いだと考えています。 --- 戦争がしばしば起きるデリケートな話題なので、私の考えが絶対に正しいとは言い切れません。 ・Qiita もう参照渡しとは言わせない https://qiita.com/mdstoy/items/2ef4ada6f88341466783 ・Qiita なぜ、Java、JavaScript、Python、Ruby等で「参照渡し」の言葉を使うべきではないのか? https://qiita.com/raccy/items/59a6ac6c818918dd9651 ・Qiita <値型>と<参照型>、<値渡し>と<参照渡し>について実行例を出す(C編) https://qiita.com/koher/items/7999a6331a385ec74672 私自身は本回答に低評価していません。誤りだとは断言できないので。
cateye

2019/11/16 09:30

“低評価していません”・・・ご気遣いなく、低評価も評価の内・・・(良かったのか悪かったのか判らないので)何もないのが一番困る。
guest

0

ベストアンサー

※回答が物凄く分かりづらかったので全改修しました。


変数を渡したとき、値は別の領域にコピーされます。

C

1#include <stdio.h> 2 3void func(int x) { 4 printf("x is %d, at %p.\n", x, &x); // x is 42, at 0x7ffcbc66937c. 5} 6 7int main(void) { 8 int a = 42; 9 printf("a is %d, at %p.\n", a, &a); // a is 42, at 0x7ffcbc66939c. 10 11 func(a); 12 13 return 0; 14}

Wandbox (実行結果は毎回変わり得ます。)

値がコピーされていても、領域が別に存在していることが分かります。
ですので、関数内でxの値をいくら書き換えてもaには影響しません。


一方グローバル変数を用いている例では、sumのコピーは発生しません。

C

1#include <stdio.h> 2 3int sum = 0; 4 5void func(void) { 6 printf("sum(in func) is %d, at %p.\n", sum, &sum); // sum(in func) is 0, at 0x600974. 7} 8 9int main(void) { 10 printf("sum(in main) is %d, at %p.\n", sum, &sum); // sum(in main) is 0, at 0x600974. 11 func(); 12 13 return 0; 14}

Wandbox

main関数からもfunc関数からも、同じ変数sumを参照していることが分かります。

旧回答

C言語は実引数を値渡しするので、関数内で新たな値を代入しても外部には全く影響しません。
変数のポインタを渡すようにすることで、関数内で変数の値を書き換えることができます。

一つ目のコードでsum変数を関数内で参照し、値を変えることができているのに

返り値と言う形で結果を受け取り、main関数内で変数を書き換えているからです。

なお、確かにsumはグローバル変数ですが、
これは『all_pointの値を更新できること』自体には関係ありません。

投稿2019/11/16 08:16

編集2019/11/16 08:30
LouiS0616

総合スコア35668

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

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

Sukabo

2019/11/16 08:30

つまり、二つ目のコードのswap関数内では新たなx, yという変数をいじっているだけだからa, bには影響がないということですよね。
LouiS0616

2019/11/16 08:33

そういうことです。 同じ領域をいじりたい場合、ポインタを渡すのが一般的です。グローバル変数にしてしまうとコード全体に影響してしまうので。
Sukabo

2019/11/16 08:36

編集前の回答しか見れていなかったので繰り返しの質問になってしまいました。 とても分かりやすい説明、ありがとうございます。
guest

0

関数の引数は、値をコピーされて関数内に渡されますんで、いくら関数内で変えても、関数の外には影響されません。

それに、後者のコードにはグローバル変数ってのは登場してませんぜ

投稿2019/11/16 08:15

編集2019/11/16 08:18
y_waiwai

総合スコア88038

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問