メモリモデル +-------+ | | セル : 1 byte = 8 bit = 0 〜 255 までの 256 +-------+ メモリ +-------+ | | <= 個々セルには、アドレス(番地)がついている +-------+ | | +-------+ | | +-------+ | | +-------+ .. +-------+ | | +-------+ セルを操作するには、そのセルのアドレスが解ればよい 個々のセルは、あたかも、C 言語の char 型変数と同じ振る舞い C 言語の変数は、連続したセルからなる いくつか ? -> sizeof 例 : sizeof ( char ) = 1 -> char 型変数はセル 1 個 例 : sizeof ( int ) = 4 -> int 型変数はセル 4 個からなる 今までの「C 言語の『変数』という概念」を、メモリのセルで説明できる C 言語では、変数名を利用して、変数を操作 変数名が解らないと操作できない !! 「変数名」を操作する方法はない メモリでは、アドレスを利用して、セルを操作 アドレスは計算できるので、知らなくても計算(作る)事で、知らないセルを操作できる -> 強力だが、危険な可能性がある ポインタ値: C 言語の(コンパイル時、実行共通の)概念 +--- アドレス値 +---+ | | +--- 型情報 | +--- size : sizeof で知る事ができる +---+-- メモリモデル | 実行時の概念 +--- 扱いかた (演算の仕方/コーディング) +-- 言語が導入 コンパイル時の概念 関数が実行時に引数で渡すのは、アドレス値だけ 型情報は、(コンパイル時の概念で、実行時はなく)渡されない == p-004.c p-004-sub.c 実行時には、関数にアドレス値しか渡されないことを悪用して アドレス値を自由に変更できる !! できるなら、やってもよい => C 言語の発想 !! それが、便利で、分かっている人が使うなら積極的にサポートする p-005.c ポインタ値 = アドレス値 + 型情報 アドレス値は、計算 ( 整数値を加える ) ができる 型情報は、値の前に、(型 *) を付けて、変更できる キャスト : 指定した(ポインタ値の)アドレス値を別の型のポインタ値(アドレス値は変わらない)に型変換する キャストの結果、アドレス値(対象)は変わらないが型が変わるので、「扱い」が変わる C 言語では、自由にポインタ値を(計算によって)作る事ができる その値が、適切(自分が参照したい変数を指す)である事を意識する必要がある !! 誰も(コンパイラも、OS もその値が適切かどうかは)見張っていない きちんと理解して、扱う必要がある(要注意) == (先週の続き) 多次元配列 : 配列の配列... -> メモリ上の連続したセルに対応する 例: char a[6]; a[0] 〜 a[5] の 6 個のようそ +-----------+ a-> a[0]| | +-----------+ a[1]| | +-----------+ a[2]| | +-----------+ a[3]| | <- a + 3 * sizeof(char) +-----------+ a[4]| | +-----------+ a[5]| | +-----------+ char b[2][3]; b[0][0], b[0][1], b[0][2], b[1][0], b[1][1], b[1][2] の合計 6 個 +-----------+ b-> b[0][0] | | b[0] は、b[0][0], b[0][1], b[0][2] という +-----------+ 三つの要素を持つ配列として扱われる b[0][1] | | b[1] も同様 +-----------+ だから、b は b[0] b[1] からなる配列 b[0][2] | | +-----------+ b[1][0] | | +-----------+ b[1][1] | | <- b + sizeof(char [3])*1 + sizeof(char) * 1 +-----------+ sizeof(char b[0] ) b[1][2] | | +-----------+ 今日の課題の 20171215-01 は、一次元配列の添え字を計算する事により、 任意の形の配列として利用可能 今日の課題は、 一次元配列を、好きな形配列にした これを援用すると... 一つの一次元配列を、複数の配列とみなす事もできる 例: int a[10] -> a[0] 〜 a[4], a[5] 〜 a[9] さらに、この考え方を推し進めると どこかに巨大な配列があって、 すきな時に好きなだけ、きりとって利用できるとうれしい 実際にこれが可能 !! C 言語の配列のサイズは、プログラム(コンパイル)時に決定する必要がある !! 一方、配列のサイズは、後(実行時)に決められると便利 !! これは矛盾している !! -> この矛盾の解決方法の一つは、最初に(無駄でも)、たくさんのサイズをとっているとよい !! 効率が悪い/無駄が生じる C 言語では、あらかじめ大きな一つ配列が用意され、 それが必要に応じて、切り取って使える様な仕組みが用意されている malloc の仕組み