「C言語/配列とポインタ」の版間の差分

削除された内容 追加された内容
__TOC__ 除去。項目が増えたので。その他、追記。
配列ポインタに対する加算 配列aの配列ポインタそのものに *pa+1 などの計算をしても、 それは決して先頭アドレス値に+1をしたものを意味せず、 *pa+1 はa[1]を意味します。 同様に*pa+2はa[2]を意味します。
34 行
 
一般に配列を格納したポインター変数 pa では、 +0 によって配列の0項目。+1によって配列の1項目、+2によって配列の2項目、・・・を参照できます。このため、上記のような<code *(pa + i)></code>というコードで、配列のそれぞれの要素を参照できます。
 
== 配列ポインタに対する加算 ==
 
配列aの配列ポインタそのものに *pa+1 などの計算をしても、
それは決して先頭アドレス値に+1をしたものを意味せず、 *pa+1 は<code>a[1]</code>を意味します。
同様に*pa+2は<code>a[2]</code>を意味します。
 
配列は必ず<code>a[i]</code>と<code>a[i+1]</code>とのアドレス間が等間隔なので、
このような処理を実装するなら、配列の先頭アドレスをコピーする際に一緒に配列のアドレス間隔もコピーすれば済みます。
 
なので、ポインタ配列の活用は、要素数がとても多い配列の場合には高速化につながります。
 
<code>&a[0]+1</code> などを表示しても、同じように<code>a[1]</code>を意味します。
 
<syntaxhighlight lang=c>
#include <stdio.h>
 
int main(void) {
int a[5] = {2, 3, 5, 7, 11};
 
for (int i = 0; i < 4; i++)
printf("%d ", a[i]); //配列aの要素を一覧表示する。
printf("\n");
 
int *pa = a; // 配列名(この場合は「a」)はアドレスを示すので「&」をつけない。
 
printf("%d ", *(pa + 2)); //ポインターpaを使って配列aの要素を表示する。
printf("\n");
 
 
printf("アドレスpaは %p \n", pa);
printf("アドレス&a[0]は %p \n", &a[0]);
printf("アドレス&a[1]は %p \n", &a[1]);
printf("アドレス&a[1]は %p \n", &a[2]);
printf("\n");
printf("アドレスpaは %p \n", pa);
printf("アドレスpa+1は %p \n", pa+1);
printf("アドレスpa+2は %p \n", pa+2);
 
printf("(&a[0]) +1の場合でも %p \n", (&a[0]) +1 );
printf("%%pでなく%%xの場合でも %x \n", (&a[0]) +1 );
 
int h = &a[0];
printf("\nどうしても整数計算的に+1したいなら\n", h +1 );
printf("int h = &a[0];によって %x \n", h +1 );
 
}
</syntaxhighlight>
 
実行結果
<pre>
2 3 5 7
5
アドレスpaは 000000000022FE20
アドレス&a[0]は 000000000022FE20
アドレス&a[1]は 000000000022FE24
アドレス&a[1]は 000000000022FE28
 
アドレスpaは 000000000022FE20
アドレスpa+1は 000000000022FE24
アドレスpa+2は 000000000022FE28
(&a[0]) +1の場合でも 000000000022FE24
%pでなく%xの場合でも 22fe24
 
どうしても整数計算的に+1したいなら
int h = &a[0];によって 22fe21
 
</pre>
 
 
では、どうしても先頭アドレス&a[0] たとえば 000000000022FE20 を整数計算的に+1したい場合(つまり単なる 000000000022FE21 のような数)、どうすればいいのでしょうか。答えは、単に int型の別変数を新規に<code>int h =&a[0];</code>で宣言し、そのhに+1を行えばいいだけです。
 
コンパイラによっては警告文が出ますが(たとえば gcc など)、しかし今回は意図通りの計算です。
 
ただし計算表示はできるものの、このようなint型を介したアドレス計算をコンパイラが非推奨にしており(なので警告文が出る)、
正式サポートはしていないので、データの欠損などの起こる可能性も考えられます。なので仕事などの本番では、int型を用いたアドレス計算は用いないほうが良いでしょう。
 
どのみち、上記例のようなint型を用いたアドレス計算には、実用価値もありません。
 
== 配列の要素数を求めるイデオム ==