へぼいいいわけ このページをアンテナに追加 RSSフィード Twitter

2009年10月12日

C言語の配列とポインタの違いを理解したい方へ

C言語配列ポインタは違います。どう違うのかWEBで調べてみると、みんな説明がバラバラで面白いです。というわけで、C言語配列ポインタの違いについて説明してみて、このWEB上の混沌としている状況をさらに悪化させようと思います。


配列

ソース
#include <stdio.h>

int main()
{
	char data[4] = "abc";

	/* アドレスを調べる */
	printf("01:%p\n", data);
	printf("02:%p\n", &data);
	printf("03:%p\n", &(data[0]));

	/* abcを表示させる */
	printf("04:%s\n", data);
	
	/* 値を書き換える */
	data[0] = 'd';
	data[1] = 'e';
	data[2] = 'f';
	printf("05:%s\n", data);
	return 0;
}
実行結果
01:0x22cd74
02:0x22cd74
03:0x22cd74
04:abc
05:def

01〜03まで、アドレスを表示させています。全て同じアドレスを指し示しています。


ここで気になるのが02の結果です。

「&」を使用して「data」のアドレスを取得していますが、同じアドレスを指し示しています。「data」は配列であってポインタでは無いため、「data」自身はアドレスを保存する領域を持っていません。でも、「data」は配列の先頭を表しているため、ややこしいことにポインタのように使えます。でも、ポインタのように使えるだけで、アドレスを保存する領域が無いため、インクリメントしたり、アドレスを代入したりすることは出来ません。

f:id:heiwaboke:20091011225627p:image

「&」でアドレスを取得しても「data」は配列自身なので「data」と「&data」は同じアドレスを指します。


ポインタ

ソース
#include <stdio.h>

int main()
{
	char *data = "abc";

	/* アドレスを調べる */
	printf("01:%p\n", data);
	printf("02:%p\n", &data);
	printf("03:%p\n", &(data[0]));

	/* abcを表示させる */
	printf("04:%s\n", data);

	/* 値を書き換える */
	data[0] = 'd';
	data[1] = 'e';
	data[2] = 'f';
	printf("05:%s\n", data);
	return 0;
}
実行結果
01:0x402020
02:0x22cd74
03:0x402020
04:abc
05:def

01〜03まで、配列と同じくアドレスを表示させています。配列の時とは違い、02が違うアドレスを指しています。

「data」はポインタのため、アドレスを保持しています。そのアドレスとは「"abc"」の先頭、つまり「'a'」のアドレスです。

「data」の領域は「"abc"」とは別の場所にあり、そのため「&」でアドレスを取得すると「data」自身の領域のアドレスを指します。

f:id:heiwaboke:20091011225628p:image


まとめ

配列はアドレスを保管するための領域を持っていないため、「&」で配列自身のアドレスを取得しても、配列自身と何も変わらない。それに対し、ポインタはアドレスを保管する変数であり、保管するための領域を持っている。ポインタ配列のように使うと、配列のときとは違いポインタ配列へのアドレスを保管する形になる。そのため、「&」を使用してアドレスを取得すると、ポインタの領域(配列へのアドレスを保管している)のアドレスが取得され、「ぽいんたのぽいんた」になる。

おまんこ23おまんこ23 2009/10/12 12:09 このスレッドもメンテお願いしますお♪
http://unkar.jp/read/gimpo.2ch.net/archives/1251286314

おまんこ24おまんこ24 2009/10/12 22:35 早速サンクスだお!

RiSKRiSK 2009/10/14 19:12 配列とポインタ云々以前の話ですが,文字列リテラルの先頭要素へのポインタを char* につっこむのはよくない作法です。
さらに,文字列リテラルを書き換えているので未定義動作を引き起こすプログラムです。これはそもそも,文字列の先頭要素へのポインタを const char* で受け取っていればすぐに気付けた問題です。

RiSKRiSK 2009/10/14 19:16 heiwaboke さんのおっしゃる「配列自身」というものは配列の先頭要素へのポインタであって,配列へのポインタではありません。たまたま同じアドレスになるかもしれませんが,data で得られるポインタは char* 型であるのに対し,&data で得られるポインタは char(*)[4] 型で,それら二つは異なるものです。

aaaaaa 2009/10/24 13:03 配列は右辺値でポインタは左辺値です

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証