第10回 ポインタと配列 - 1次元配列 1次元配列 ポインタとは? オブジェクトと&演算子 ポインタとオブジェクト 一次元配列とポインタの関係 一次元配列 配列…変数の箱を複数用意したもの 配列の宣言 型 配列名[配列サイズ]; 例) int 型の配列(10個)の場合 int array[10]; 配列要素の表現: 配列名[添え字] …添え 字(インデックス)は0から(したがって、サイズ -1まで) 配列 array[10] array[0] array[1] array[2] array[9] 配列変数の初期化 配列変数の初期化は、宣言と同時に右辺に{}で 要素を,で区切ったリストで設定 配列サイズは、初期化したときの要素数分だけ自 動で取られる 例) char a[] = { 0, 1, 2, 3, 4, 5}; 6個分、配列がとられる オブジェクトとアドレス - &演算子 オブジェクト … 変数などの抽象的表現 アドレス … 変数(オブジェクト)は、メモリ上 に領域が割り当てられる cf.) 自動変数、静的変数 &演算子... オブジェクトが割り当てられたメ モリ上でのアドレスを指す場合に用いる メモリ上 例) int hoge = 10; の場合 &hoge hoge 10 ポインタの導入 ポインタ変数 ... メモリ上のアドレスを指し示すため の変数 ポインタ変数の宣言: 型名 *ポインタ変数名; 例) char *str; *演算子で、指しているアドレスの中身(保持してい る値)を示す ポインタ変数名だけだと、アドレスを示す char ch = 10; char *str; str = &ch; メモリ上 str *str &ch 10 ch ポインタとオブジェクトの関係 アドレス = アドレス ポインタ変数 = &変数(オブジェクト) 例) int a; int *p; p = &a; /* ポインタpは変数aのアドレスを指す */ 中身 = 中身 *ポインタ変数 = 変数(オブジェクト) 例) 上記の変数aとポインタ変数p について *p = 0; /* ポインタpを使って変数aに0を代入 */ ポインタに対する演算 ポインタ変数に対する演算は、そのポインタ の型に応じて行われる int 型のポインタのインクリメント→ 4 byte 増加 char 型のポインタのインクリメント→1 byte 増加 ポインタに対する演算(インクリメント・デクリメ ント)を行う場合は、そのポインタの型に注意 する ポインタを使用する場合の注意 ポインタは、必ず初期化してから使用(代入)する ポインタの初期化とは、どこかのアドレスを指させることで ある 例) int hoge; int *ptr; ptr = &hoge; /* 初期化 */ 初期化していないポインタは、バグの温床となる いきなり代入しようとするな!! ポインタと1次元配列の関係 ポインタ変数と配列変数は密接な関係がある ポインタは配列に書き直すことが可能(1次元のみ) ⇔ 逆も可(配列をポイ ンタで表現) ポインタと配列の大きな違いは、ポインタが初期化しないと指しているア ドレスが保証できないのに対し、配列は自動でメモリ領域が確保されて そこを自動で指す点である。 ポインタ変数 == &配列変数[添え字] *ポインタ変数 == 配列変数[添え字] ポインタ表現 ptr *ptr ptr + 1 *(ptr + 1) 配列表現 &a[0] a[0] &a[1] a[1] 関数呼び出し(アドレス渡し) - call by reference 関数呼び出しの実引数リストにオブジェクトのアドレスを指定することに よって、直接オブジェクト自体を関数に渡すことができる 上記の場合、関数の定義(本体)の仮引数リストはポインタ変数で受けな ければならない(アドレスをもらうため) オブジェクトそのものを渡すことによって、呼び出し元の関数へ引数の変 数への変更を反映させることができる cf.) 値渡し(call by value)... 引数がコピーされるため、呼び出し元には引 数の変数に対する変更は反映されない 例) アドレス渡しによるswap 関数の呼び出し(call by reference) 呼び出される側(関数定義): 呼び出し側: void swap(int *a, int *b){ int hoge; int tmp; int geho; swap(&hoge,&geho); tmp = *a; *a = *b; *b = tmp; }
© Copyright 2024 ExpyDoc