C プログラミング Ⅱ の基礎
アドレス 変数のために用意されたメモリ領域の位置 アドレス 0x1000 0x1001 0x100 0x1003 0x1004 0x100 0x1006 0x1007 0x1008 0x1009 0x100A 0x100B メモリ 整数型の変数を宣言 int ; アドレス 0x1000 0x1001 0x100 0x1003 0x1004 0x100 0x1006 0x1007 0x1008 0x1009 0x100A 0x100B メモリ 変数 のメモリ領域が確保される
変数のアドレスの参照 アドレス演算子を用いた変数のアドレスの参照 int = ; アドレス演算子 (&) & 変数名 printf(" 変数 の値は %d です. n", ); printf(" 変数 のアドレスは %p です. n", & ); return 0; 変数 の値は です. 変数 のアドレスは 0x1004 です. この値が出力される 変数 のアドレスを出力 アドレス 0x1000 0x1001 0x100 0x1003 0x1004 0x100 0x1006 0x1007 0x1008 0x1009 0x100A 0x100B メモリ 3
アドレスを格納する変数 int = ; int *p; の宣言 型名 * 名 ; p = &; p の宣言 変数 のアドレスを p に格納 = ; p = &; 0x1004 p p には変数 のアドレス 0x1004 が格納される 0x1004 0x100 0x1006 0x1007 p p は変数 を指す 変数の型との型は一致している必要がある 4
による変数の値の参照 間接参照演算子を用いたによる変数の値の参照 間接参照演算子 (*) * 名 ; * p 同じ意味 ただし, あらかじめ p = &; が実行されていることが条件 int = ; int *p; p = &; printf("p が指す変数の値は %d です. n", *p ); p が指す変数の値は です.
のまとめ int 型変数 について & 変数 変数 のアドレス int 型の p について p = &; としたとき p *p 変数 のアドレスを格納した ( p は変数 を指している ) p が格納しているアドレスに記憶領域が設定されている変数 ( p が指している変数 の値 ) 6
への別のアドレスの代入 に別のアドレスを代入する int =, b = 10; int *p; p は変数 を指す p = &; printf("pが指す変数の値は %dです. n", *p ); p = &; 10 b p p = &b; printf("p が指す変数の値は %d です. n", *p ); p = &b; p は変数 b を指す p p が指す変数の値は です. p が指す変数の値は 10 です. 10 b 7
からへのアドレスの代入 に格納されているアドレスを別のに代入する int = ; int *p, *pb; p は変数 を指す p = &; p p = &; pb = p; pb も, p が指している変数 ( ) を指すようにする pb printf("p が指す変数の値は %d です. n", *p ); printf("pb が指す変数の値は %d です. n", *pb ); pb = p; p p が指す変数の値は です. pb が指す変数の値は です. pb 8
による変数の値の変更 をもちいて, そのが指す変数の値を変更する int = ; int *p; p は変数 を指す p = &; printf("pが指す変数の値は %dです. n", *p ); *p = 10; printf("p が指す変数の値は %d です. n", *p ); p が指している変数 ( ) の値を変更する = 10; と書いたのと同じ意味 p = &; p *p = 10; 10 p アスタリスク * を付けること! p が指す変数の値は です. p が指す変数の値は 10 です. 9
引数と つの変数の値を交換する関数を作成してみる void swp(int x, int y); int =, b = ; printf(" の値は %d です. n", ); printf("b の値は %d です. n", b); printf(" 交換します. n"); void swp(int x, int y) int tmp; tmp = x; x = y; y = tmp; 引数で受け取った値を交換する swp(, b); と b の値を交換したい 実行結果 printf(" の値は %d です. n", ); printf("b の値は %d です. n", b); return 0; の値は です. b の値は です. 交換します. の値は です. b の値は です. 交換できていない! 10
引数と 値渡し 実引数の値だけが関数の仮引数に渡される int =, b = ; swp(, b); printf(" = %d b = %d n",, b); void swp(int x, int y) int tmp; tmp = x; x = y; y = tmp; このままでは,b の値は交換されない min 関数 swp 関数 x x b y y コピー swp 関数の x,y の値が交換されるだけである = b = 11
引数と 参照渡し 実引数のアドレスを関数に渡す受け取る側の関数の仮引数はとする int =, b = ;,b のアドレスを渡す swp(&, &b); printf(" = %d b = %d n",, b); min 関数 b min 関数 b void swp(int *x, int *y) int tmp; tmp = *x; *x = *y; *y = tmp; x,y を用いて変数,b の値を交換する = b = swp 関数 x y x y tmp swp 関数 tmp x,y が指す変数,b の値を交換する 1
引数と 参照渡しを用いれば, 関数で計算した複数の値を呼び出し側に返すことが可能となる w にも s にも 7 が入る int keisn(int x, int t); int =, b = ; int w, s; 複数の値を返すことができない例 の値と b の値の和と差の計算を keisn 関数で行いたい w = keisn(, b); s = keisn(, b); printf("w = %d s = %d n", w, s); int keisn(int x, int y) return (x + y); x + y の計算結果しか返せない return (x y); return (x - y); は実行されない w = 7 s = 7 min 関数 w s 7 7 w s keisn 関数 x + y 7 13
引数と 参照渡しを用いれば, 関数で計算した複数の値を呼び出し側に返すことが可能となる void keisn(int x, int y, int *p, int *q); int =, b = ; int w, s; w と s のアドレスを渡す keisn(, b, &w, &s ); printf("w = %d s = %d n", w, s); void keisn(int x, int y, int *p, int *q ) *p = x + y; *q = x y; 足し算, 引き算の結果が w と s に入る w = 7 s = 3 p は w を指し, q は s を指している min 関数 w s 7 3 w s keisn 関数 x y 7 + - 3 p q 14