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

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

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

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

Q&A

解決済

3回答

1089閲覧

C言語 ポインターの基礎

Tubasa1995

総合スコア83

C

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

0グッド

0クリップ

投稿2021/08/27 13:47

機能からC言語の勉強をはじめました。
ポインターに関して分からないところがあるので教えてください。
下記のコードをためすと

#include <stdio.h> void setTen(int *a){ *a=100000; } int main(void){ int a=230; setTen(&a); printf("%d\n",a); return 0; }

結果としては

100000

が出力されると思うのですが、いまいち理解できません。
・int a=230
は適当にaという変数に230を設定

・setTen(&a)
はaのアドレスを引数?として関数呼び出し

・printf("%d\n",a)
はaを単純に表示させるだけ

という以上の認識で正しいですか?
いまいち理解できないのは、aはaという場所にある値を出力しているのだと思うのですが
setTenという関数の中では
aというポインタしか定義していないのに
なぜaを出力すると*aの100000が出力されるのでしょうか。

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

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

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

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

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

guest

回答3

0

ベストアンサー

質問文にあるmain()関数に関する動作の記述はだいたい合っていると思います。
疑問点は、setTen()関数がどのような動作をしているのかが分からないということだと思います。

いまいち理解できないのは、aはaという場所にある値を出力しているのだと思うのですが
setTenという関数の中では
aというポインタしか定義していないのに
なぜaを出力すると*aの100000が出力されるのでしょうか。

確認のために、もしかして間違って理解しているかもしれないと思われるところを2点指摘しておきます。

  1. main()で使用されている変数「a」とsetTen()の変数「a」の変数名には関連がありません。
  2. setTen()には、「*a」という変数はありません。変数は「a」です。

1については他の回答者さんが行われているように混乱を避けるためにsetTen()では別の変数名に置き換えてみると良いかもしれません。(以下の説明ではpointerという変数にしてみました。)

void setTen(int *pointer){ *pointer=100000; }

2について

  • 仮引数の「int *pointer」という部分は、「*pointer」という変数ではなく、「pointer」という変数でそれがint型のポインタ変数(int *)である、という風に解釈します。
  • 「*pointer=100000;」の部分は、「pointer」という変数に値を代入しているのではなく、 「pointer」というポインタ型変数の指す変数実体へ値を代入するという意味となります。ポインタ変数の実体のほうをを対象とするために「」という演算子を付けて「*pointer」としています。

pointer」という記述が2回出ていますが、「int pointer」の「」は型宣言の一部としての「」であり、「pointer=100000;」の「」はポインタ実体化の演算子であり、それぞれ意味合いが違っており区別して理解する必要があります。

投稿2021/08/27 23:38

編集2021/08/27 23:54
hidezzz

総合スコア1248

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

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

0

ポインタについてはあっさりと、
「各変数にはC言語の定める『アドレス』が設けられているので、名前付きの変数であっても、名前の代わりにアドレスを指定して操作することができる ( 名前の無い変数ならアドレスを通じて操作するしかない )」
という理解でどうぞ。

その上で、関数呼び出ししているとどのようになるのか把握しておく必要があります。

void setTen(int *p){ *p=100000; } int main(void){ int a=230; setTen(&a); printf("%d\n",a); return 0; }

元のこのプログラム ( ちょっと変数名変えてます ) で setTen を呼び出している部分は、次のような処理をしているのと同じことです。
※引数として &a を渡すのは、関数のパラメータ p に代入 ( コピーを保存 ) しているのと同じ。

int a=230; { int *p=&a; // (int*)型の p に初期値 &a を与えている形 *p=100000; } printf("%d\n",a);

ポインタの説明の時に、「ポインタ使わない場合は関数内での値の変更が呼び出し元に伝わりませんよ」と対比されるような、次のコードの例を考えますと。
※実用的には無意味なので、あくまで動作の対比例としてだけ見てください。プログラムとしては230が出力されます

void dummy(int x){ x=100000; } int main(void){ int a=230; dummy(a); printf("%d\n",a); return 0; }

こちらは次のようになって、関数内での100000の代入が元の aに反映される形にはなりません。

int a=230; { int x=a; x=100000; } printf("%d\n",a);

投稿2021/08/27 16:10

angel_p_57

総合スコア1681

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

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

0

こんばんは。一つずつ回答していきます。
・int a=230 : aに230を代入
・setTen(&a) : aのアドレスをsetTenという関数に引数として渡して実行
・printf(…) : aの表示
という認識でいいと思います。

変数を定義した時点でその変数はメモリのどこかに格納されます。よって自動的にアドレスは割り振られるので、アドレスを持たない変数は存在しません。

setTenに渡している値はアドレスです。setTen関数の中で行われている作業は、渡されたアドレス(つまり&a)が指している変数の中身に100000を代入しています。setTen関数の中で定義されているポインタ型のaはmain関数のaとは別物なので、*aとするとポインタの中身を表すことになります。
setTen関数のポインタ型変数の名前を変えてみると理解が深まるのではないでしょうか。

つたない文章ですみません。参考になれば幸いです。

投稿2021/08/27 15:35

pochi-pochi

総合スコア28

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

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

angel_p_57

2021/08/27 15:52

> 変数を定義した時点でその変数はメモリのどこかに格納されます。 そのような決まりはないので、説明として余計でしょう。
pepperleaf

2021/08/28 01:12

> アドレスを持たない変数は存在しません。 確かに不正確。ただ、今回は &a でアドレスを取ってるから、メモリのどっかに格納されるでしょうね。 ある条件下では、レジスタに格納されて終わりかも知れないですが。
pochi-pochi

2021/08/28 01:17

補足していただきありがとうございます。勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問