配列型は,要素数(サイズ)と要素型の2つで特徴化されるデータであることを 9.1 で見ました。この特徴は,メモリ上では,次のような意味を持ちます。すなわち,「要素型をもつオブジェクトが連続してメモリに記憶されるデータ」という意味です。更に,これに次の文法が加わります。
T
型の配列」型をもつ式は,その配列の第1要素を指し示すT
へのポインタ型に変換される。但し,それは左辺値ではない。sizeof
演算子や _Alignof
演算子,&
演算子(後出 10.7)や初期化の場合を除きます。また,register
記憶域クラスを持つ場合,動作は未定義になります。
ここで「第1要素を指し示すポインタ(pointer that points to the initial element)」とは,例えば,宣言
char str[8] = "ABCDEFG"
の場合,str
自体が,配列の第1要素 'A'
を記憶しているアドレスを指し示す char
へのポインタになっているという意味です。
/* Example 10.1 */ #include <stdio.h> int main(void) { char str[] = "ABCDEFG"; printf("str[0] = '%c' [%p]\n", str[0], str); return 0; }
printf
関数内の変換指定子 %p
はポインタの(処理系依存の)出力です。ここでは,上の文法に従い,str
が第1要素を指し示す char
へのポインタになっているため,配列の第1要素のアドレスが出力されます。
実行結果です。
str[0] = 'A' [0xbffffa18]
第1要素のアドレスは 0xbffffa18
です。(十六進法の読み方は整数定数を参照。)char
型は1バイトなので,次のようにメモリに値が記憶されていることになります。
+------------+------------+------------+------------+ | 0xbffffa18 | 0xbffffa19 | 0xbffffa1a | 0xbffffa1b | アドレス +------------+------------+------------+------------+ | 'A' | 'B' | 'C' | 'D' | 値 +------------+------------+------------+------------+ +------------+------------+------------+------------+ | 0xbffffa1c | 0xbffffa1d | 0xbffffa1e | 0xbffffa1f | アドレス +------------+------------+------------+------------+ | 'E' | 'F' | 'G' | '\0' | 値 +------------+------------+------------+------------+
+------------+------------+------------+------------+ | 0xbffffa18 | 0xbffffa19 | 0xbffffa1a | 0xbffffa1b | アドレス +------------+------------+------------+------------+ | 0x41 | 0x42 | 0x43 | 0x44 | 値 +------------+------------+------------+------------+ +------------+------------+------------+------------+ | 0xbffffa1c | 0xbffffa1d | 0xbffffa1e | 0xbffffa1f | アドレス +------------+------------+------------+------------+ | 0x45 | 0x46 | 0x47 | 0x00 | 値 +------------+------------+------------+------------+
配列は要素型(この場合 char
型)のオブジェクトが連続して記憶されるデータです。
/* Example 10.2 */ #include <stdio.h> int main(void) { unsigned int m[5] = {3, 7, 10}; printf("m[0] = %d [%p]\n", m[0], m); return 0; }
実行結果です。
m[0] = 3 [0xbffffa78]
奥山研究室では sizeof(int) = 4
ですので,次のように値がメモリに記憶されていることになります。
+------------+------------+------------+------------+ | 0xbffffa78 | 0xbffffa79 | 0xbffffa7a | 0xbffffa7b | アドレス +------------+------------+------------+------------+ | 0x00 | 0x00 | 0x00 | 0x03 | 値 +------------+------------+------------+------------+ +------------+------------+------------+------------+ | 0xbffffa7c | 0xbffffa7d | 0xbffffa7e | 0xbffffa7f | アドレス +------------+------------+------------+------------+ | 0x00 | 0x00 | 0x00 | 0x07 | 値 +------------+------------+------------+------------+ +------------+------------+------------+------------+ | 0xbffffa80 | 0xbffffa81 | 0xbffffa82 | 0xbffffa83 | アドレス +------------+------------+------------+------------+ | 0x00 | 0x00 | 0x00 | 0x0a | 値 +------------+------------+------------+------------+ +------------+------------+------------+------------+ | 0xbffffa84 | 0xbffffa85 | 0xbffffa86 | 0xbffffa87 | アドレス +------------+------------+------------+------------+ | 0x00 | 0x00 | 0x00 | 0x00 | 値 +------------+------------+------------+------------+ +------------+------------+------------+------------+ | 0xbffffa88 | 0xbffffa89 | 0xbffffa8a | 0xbffffa8b | アドレス +------------+------------+------------+------------+ | 0x00 | 0x00 | 0x00 | 0x00 | 値 +------------+------------+------------+------------+
配列は要素型(この場合 int
型)のオブジェクトが連続して記憶されるデータです。