ポインタ

C言語のポインタは、変数のメモリ上の位置、つまりアドレスを保持する変数である。それぞれの変数は一意のアドレスを持ち、それはメモリ上の変数の位置を示す。ポインタはこのアドレスを指している。それがポインタの名前の由来である。

存在している
保持している
示している
メモリ: 図書館
アドレス: 書棚の位置1
変数x: 本
ポインタp: カード

この図では、メモリ(図書館)にはアドレス(書棚の位置)が存在し、それぞれのアドレスには変数(本)が保存されている。そして、各ポインタ(カード)はそれぞれの変数のアドレス(書棚の位置)を指している。この概念を理解することで、C言語におけるメモリ管理とポインタの役割が明らかになる。

ポインタの宣言と初期化は以下のように行います。例えば、int型の変数を指し示すポインタは"int "と宣言します。変数名の前にアスタリスク()をつけて宣言します。

上記の例では、&演算子を使用して、変数numのアドレスをポインタptrに代入しています。次に、ポインタが指し示すメモリ上の値にアクセスするために、*演算子を使用します。

他の型のポインタも同様に宣言します。例えば、double型のポインタは次のように宣言します:

ポインタが指し示す変数を使用する際にも*を使います。ただし、これはポインタ変数の宣言時の*とは異なる意味で使われます。

実行結果

※ 最初は,あまり「アドレス」は意識しなくて良い.関数に渡すときに,コピーではなく,変数の実体を渡している,というような感じ.

※ 「アドレス」を意識した応用は,また,別の機会に学習. fd サンプルコード 例1)基本文法の練習

このコードでは、int型の変数xを定義し、その後int型のポインタpを定義する。そして、xのアドレスをpに代入する。これにより、pxを指し、xを間接的に操作できる。

例2)いろいろな書き方の例.

実行結果

 

##

例3)ポインタ変数を使って、2つの整数値を交換する関数swapを作成せよ。

このコードでは、関数swapは二つのint型のポインタを引数として受け取る。それぞれのポインタは、交換したい二つの整数変数のアドレスを指している。関数内部で、ポインタを通じて直接これらの変数の値を変更し、それらの値を交換している。それにより、関数呼び出し元のxyの値が交換される。

注意点として、関数を呼び出す際には、引数として変数のアドレス(&xおよび&y)を渡す必要がある。これにより、関数内部で変数の実際の値を変更することができる。これがポインタを使用する主な目的の一つであり、C言語の重要な概念である。

Q&A

質問1: tempはポインタであるか?

回答: いいえ、tempはポインタではない。tempは通常の整数型(int)の変数で、一時的に値を保存するために使用される。この場合、*aの値(aが指す値)を一時的に保存している。


質問2: int temp = *a; *a = *b; *b = temp; このコードはアドレスを渡しているのか、それとも値を渡しているのか?

回答: このコードでは、値が渡されている。具体的には、*a*bは、ポインタabが指す値を参照する。つまり、アドレスではなく、そのアドレスに格納されている値を直接操作している。


質問3: ポインタpに値を割り当てるときにp = &vと書くと、pは変数vのアドレスを指す。では、なぜswap関数を呼び出すときには&x&yを引数として渡すのか? swap関数の定義はswap(int *a, int *b)だが、これは*a = &xを意味するのか?

回答: swap(int *a, int *b)関数はint型のポインタを引数として受け取る。したがって、この関数を呼び出すときには、アドレスを引数として渡す必要がある。つまり、&x&yを引数として渡す。&xは変数xのアドレスを表し、&yは変数yのアドレスを表す。これらのアドレスは関数に渡され、abがこれらのアドレスを指すようになる。よって、*a = &xではなく、a = &xが正しい。


質問4(関数の復習): ポインタを使用しないでswap関数を作成することは可能ですか? その場合、その動作はどのようになるか?

回答: C言語では、ポインタを使用しないと、関数内部で直接変数の値を交換することはできない。これは、C言語がデフォルトで値渡しを行い、関数内部での変更が呼び出し元の変数に影響を与えないためである。仮に,以下のようなswap_without_pointer関数を作成したとする:

このコードを実行すると、"交換後"のxyの値は交換されていないことがわかります。これは、swap_without_pointer関数が値をコピーして使用しているため、関数内部での値の変更がxyに反映されないからです。これに対し、先ほどのswap関数では、ポインタを使用してxyの実際の値を直接変更しています。この差異は、C言語における値渡しとポインタの使用の違いを明確に示しています。

Alt text

例4)受け取った変数を,その変数の3乗に置き換える関数.

 

 

配列を引数とする関数

配列はベクトルのようなものであったので,例えば,

など,ベクトルを操作する関数を作りたいときには,配列を引数とする関数を作ればよい.

プログラム例)

注意)

上のプログラムの実行例)2回目に表示された r の値が書き換わっているのに注意.

参考)配列を引数とする関数で,うっかり,引数として受け取った変数を書き換えてしまうのを防ぎたい場合には const をつけておく.下のプログラムは,エラーになり,コンパイルできない.

##

宿題1: 関数 update を実行したら,x,y,z の値が更新されるように,下の書きかけのプログラムを完成させよ.

注意

 

宿題2:

一組の学生の成績が配列に保存されています。あなたのタスクは以下の機能を持つプログラムを作成することである:

  1. 全生徒の成績の合計を計算する関数。

  2. 全生徒の成績の平均を計算する関数。

プログラムは以下の要件を満たす必要がある:


この問題では、配列を引数として受け取る2つの関数を完成させることが求められている:calc_total_scoreは全生徒の成績の合計を計算し、calc_avg_scoreは全生徒の成績の平均を計算する。また、main関数内でこれらの関数の結果を出力するコードも追加する必要がある。