(復習)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);
}