(復習)C言語の関数呼出しは値渡しである (List 10-1)。 つまり、ふつうは関数の中で呼出し側の変数を変更することはできない。
register
変数などの例外を除き)メモリ上のアドレス(address)がある。
単項&演算子を変数(や配列の要素など=演算子の左辺に置けるもの)に適用すると、 そのアドレスが得られる。 単項&演算子はアドレス演算子とも呼ばれる。 (List 10-2)
アドレスをprintf
で出力するときの書式指定は%p
である。
*
を変数名の前につける。
(List 10-3)
int sato = 178; int *isako; isako = &sato; /* isakoは int型のオブジェクトのアドレスを格納することができる。 */ /* “isakoはsatoを指す”という。 */
isako
はint
型のオブジェクトを指すためのポインタ型
(“int
へのポインタ型”)である。
(*
の部分が主でint
が従である。)
なお、型の一部であることを強調するために*を型のほうにくっつけて、
int* isako;のような書き方をすることもある。(意味はまったく変わらない。)
ポインタ変数宣言の*
はそれぞれの変数名の前につける必要がある。
int *isako, hiroko; /* isakoはintへのポインタ型、hirokoはint型になる。*/
int* isako, hiroko; /* intのほうに*をくっつけても同じ。 isakoはintへのポインタ型、hirokoはint型になる。*/
int *isako, *hiroko; /* isakoも hirokoもintへのポインタ型になる。*/
*
演算子をつけると、それが指すオブジェクトそのものを表す。
単項*
演算子は間接演算子とも呼ばれる。
(List 10-3)
*hiroko = 180; /* hirorkoの指すオブジェクトに180を代入 */ /* この例の場合 masaki = 180と同じ効果を持つ */
scanf
関数とポインタscanf
関数でint
型(%dに対応)や、
double
型(%lf
に対応)を受取るとき、変数の前に&
をつけたのも、
関数から呼出し側の変数の値を変更するためである。
ポインタの型は、それが指すオブジェクトの型と正しく対応しなければならない。 (List 10-9)
この点は、ポインタのインクリメント・デクリメント(後述)のとき、さらに重要になる。
ポインタは配列の要素を指すこともできる。 (List 10-10)
int vc[5] = {10, 20, 30, 40, 50}; int *ptr = &vc[0];&vc[0]で配列の先頭要素のアドレスを表す。 (p.177 演算子の一覧表参照)
注意:
int *ptr; ptr = &vc[0];と同じ意味になる。
int *ptr; *ptr = &vc[0];ではないので、注意が必要である。
ptr + i は、(配列の要素の型にかかわらず)ptrが指す要素の i 個後ろの要素を指すポインタになる。
* (ptr + i)は ptr[i]と書くこともできる。(2つの書き方はCではまったく等価である。)
[]を伴わず現れた配列名は、配列の先頭要素へのポインタと見なされる (List 10-11)。 ただし、sizeofのパラメータとなるときなど、いくつかの例外がある。
void int_set (int *vc, int no, int val) { … }と書いてもまったく意味は同じである。
以下のプログラムはどこが間違っているか?
#include <stdio.h> /*--- n1とn2の和・差をsumとdiffに格納 ---*/ void sum_diff(int n1, int n2, int *sum, int *diff) { *sum = n1 + n2; *diff = (n1 > n2) ? n1 - n2 : n2 - n1; } int main(void) { int na, nb; int *wa, *sa; /* ← ここを変えた */ puts("二つの整数を入力してください。"); printf("整数A:"); scanf("%d", &na); printf("整数B:"); scanf("%d", &nb); sum_diff(na, nb, wa, sa); printf("和は%dです。\n差は%dです。\n", *wa, *sa); return (0); }
#include <stdio.h> int *sum_diff(int n1, int n2) { int ret[2]; ret[0] = n1 + n2; ret[1] = (n1 > n2) ? n1 - n2 : n2 - n1; return &ret[0]; /* 先頭要素へのポインタを返す */ } int main(void) { int na, nb; int *wasa; puts("二つの整数を入力してください。"); printf("整数A:"); scanf("%d", &na); printf("整数B:"); scanf("%d", &nb); wasa = sum_diff(na, nb); printf("和は%dです。\n差は%dです。\n", wasa[0], wasa[1]); return (0); }