/ 最近 .rdf 追記 編集 設定 本棚

脳log[20080709] > (Cの)ポインタ (ときどきの雑記帖 i戦士篇)



2008年07月09日 (水) 自分で一通り納得してしまうと、解らなかったことが不思議で、恥ずかしくなるくらい当たり前のことに思える。(実際そうでしょう)

> (Cの)ポインタ (ときどきの雑記帖 i戦士篇)

まあ、ポインタと配列は一緒とか云っている人は、一遍シンデミル? int array[なんかでかいすうじ]; なグローバルな実体を extern int *array; で参照してはまればいいと思うよw

手っ取り早く確かめるのはこんなんで。

たぶんSEGVで落ちるはず。

なぜ SEGVで落ちるのかわからなかったので、試してみた。

 a.c

/* cmd /V:ON
	SetEnv
	cl a.c foo.c bar.c
*/
#include <stdio.h>
void foo(); // foo.c
void bar(); // bar.c

char array[256];

int main()
{
	printf("main:    :array: %p\n", array);
	printf("main:addr:array: %p\n", &array);
	foo();
	printf("%s\n", array);
	bar();
	printf("%s\n", array);
	return 0;
}

 foo.c

配列(array)を配列(char[])として参照。

extern char array[]; // a.c

void foo()
{
	printf("foo :    :array: %p\n", array);
	printf("foo :addr:array: %p\n", &array);
	strcpy(array, "hello, foo world");
}

 bar.c

配列(array)をポインタ(char*)として参照。

extern char *array; // a.c

void bar()
{
	printf("bar :    :array: %p\n", array);
	printf("bar :addr:array: %p\n", &array);
	strcpy(array, "hello, bar world");
}

 出力 (<以降は注釈。>以降は考察)

main:    :array: 0040DAA0 < char array[]
main:addr:array: 0040DAA0 > &array == array
foo :    :array: 0040DAA0 > foo:array == array
foo :addr:array: 0040DAA0 > &foo:array == foo:array
hello, foo world
bar :    :array: 6C6C6568 < 6C(l) 6C(l) 65(e) 68(h)
bar :addr:array: 0040DAA0 > &bar:array が arrayと同じ
(a.exe は動作を停止しました)

確かに落ちた。

 確認

  • 配列はアドレスを取っても配列?*
  • ポインタはメモリ上に確保された値(だから操作も可能)だが配列名は違う。配列名で得られるアドレスはメモリ上に存在しない。
  • 変数名は(その時々で)特定のメモリアドレスと不可分の存在。そのアドレスの指すメモリイメージをどう解釈し、プログラマに提示するかは変数の型に依存する。

例えば arrayと書いたときに得られるイメージが 6C6C6568... だったとする。これを charと解釈すれば 'h'(68h) になるし、intと解釈すれば 1819043176(6C6C6568h) になる。shortなら 25960(6568h)。では char* なら? そのまま 6C6C6568。(ポインタのサイズが 64-bitなら、あと 4バイト先まで読むことになるが)。ではでは char[]なら? 6C6C6568... というメモリ領域を指すアドレスが手に入る。

 こういうこと?

arrayとラベルされたメモリ領域(6C6C6568...)が存在するときに、それをポインタとして扱った場合と、配列として扱った場合では、得られるものがまるで違う。(6C6C6568というメモリ上の値か、そのアドレスか)

配列とポインタが混同されるのはどちらもアドレスが得られるから。違うのはそのときその変数が参照しているメモリイメージ。配列変数は配列の中身が格納された領域を参照しながらそのアドレスを返すが、ポインタ変数はアドレスが格納された領域を参照しており、その内容をそのまま返している。

* 違うみたい。>http://www.kt.rim.or.jp/%7ekbk/zakkicho/08/zakkicho0808a.html#D20080809-2