配列ポインタのメモリレイアウトとインスタンス

1893 ワード

まず、ソースコードをテストします.
#include <stdio.h>

int main(void)
{
	char a[] = "abcd";
	char (*p3)[5] = &a;
	char (*p4)[6] = (char *)a;
/* 	
	p3 = &a;
	p4 = a; */
	
	printf("p3 = 0x%x
",(unsigned int)p3); printf("p4 = 0x%x
",(unsigned int)p4); printf("p3+1 = 0x%x
",(unsigned int)(p3+1)); printf("p4+1 = 0x%x
",(unsigned int)(p4+1)); return 0; }

>gcc -Wall p3add1.c p3add1.c: In function 'main': p3add1.c:6:18: warning: initialization from incompatible pointer type [enabled b y default] ./a.exe p3 = 0x22ff43 p4 = 0x22ff43 p3+1 = 0x22ff48 p4+1 = 0x22ff49
printf文はprintf(「p 3=0 x%x」(unsigned int)p 3)と書くのが望ましい.そうでない場合、gcc-Wallオプションでコンパイルすると、次の警告が表示されます.
p3add1.c:12:2: warning: format '%x' expects argument of type 'unsigned int', but  argument 2 has type 'char (*)[3]' [-Wformat]
initialization from incompatible pointer type[enabled by default]という警告については、私も解決方法が見つかりません.どなたか注意してください.ありがとうございます.
まずp 3がどのように定義されているかを見てみましょう.p 3を知っていれば、p 4も難しくない:(*p 3)[5]の有了(),()の優先度は[]より高く、「*」号とp 3は1つのポインタの定義を構成し、ポインタ変数名はp 3であり、intは配列の内容、すなわち配列の各要素を修飾する.配列はここには名前がなく、匿名の配列です.では、p 3は5つのintタイプのデータを含む配列、すなわち配列ポインタを指すポインタであることがわかります.
&aは配列全体のアドレスをとることを意味し、aは配列の先頭要素のアドレスを取ることを意味する.char (*p3)[5] = &a; char (*p4)[6] = a; この2つの文の意味は次のとおりです.
配列全体のアドレスをp 3に割り当て,&a[0]の値をp 4に割り当てる.
そして、p 3+1とp 4+1の後、p 3とp 4のアドレスに対応するn単位のオフセット量(p 3のn=5、p 4のn=6)を加える、上記の結果が得られる.
実は、配列aの大きさは重要ではなく、有効な配列であればよい.char (*p3)[5] = &a; char (*p4)[6] = a; この2つの操作は、2つのポインタ変数に2つのアドレスを割り当てるだけです.
まだ
(unsigned int)(p3+1)
の後ろの括弧は必ず加えなければなりません.そうしないと、unsigned intのデータに1を加えます.配列単位を加えるのではありません.