ポインタ演算
ポインタの式
ポインタも変数の一種であるということは話しました
ポインタも他の変数と同様にデータ型などが存在し、変数同様に扱えます
しかし、注意しなければいけない点がいくつかあります
ポインタも変数のように式を使った算術が可能ですが整数以外はできないということを覚えてください
ポインタに浮動小数点などの演算はできませんし、加えることもできません
つまり、ポインタの演算には整数による加減算のみということです
それ以外の算術は実行できません
それと、ポインタ変数と通常の変数の算術の大きな違いなのですが
インクリメントとデクリメント演算子を使った算術では、ポインタ変数は不思議な結果を出します
次のプログラムを見てみましょう
#include <stdio.h>
int main()
{
int ary[2] = { 1000 , 2000 };
int *po;
po = &ary[0];
printf("po\t = %x\n" , po);
po++;
printf("po++\t = %x\n" , po);
printf("*po++\t = %d" , *po);
return 0;
}
環境で出力される結果はばらばらですが
たとえば、このときpoに代入されたメモリアドレスが10fd00だとしましょう
すると次のような結果になります
po = 10fd00
po++ = 10fd04
*po++ = 2000
普通インクリメントされたことを考えると1加算されて 10fd01 になるように思えます
しかし、ポインタのデータ型がintなので整数は4バイト(環境で異なる)の長さとして処理されます
つまり配列の要素が4バイトごとに並んでいるので、1加算するとポインタの値もも4バイト増えるのです
これはデクリメントでも同じことが言え、当然floatやdoubleならば、そのバイト長に合わせてポインタの値が変化します
char型の場合は1バイトなので、この場合は通常の値のように加減算されますけどね☆
もう一つ注意ですが、間接参照でインクリメントする場合には注意が必要です
*po++
とやると、多くの人の期待に反した結果が得られると思われます
このときは、アドレスが指す変数ではなくポインタの値がインクリメントされてアドレスを参照されます
結果的に *po++ だけではポインタが格納している値をインクリメントしたが、参照する意味がないので処理系によっては警告が出ます
(代入文の場合、=よりインクリメントの方が優先度が低いので結局意味をもちません)
もし、間接参照でアドレスの変数の内容に対してインクリメントやデクリメントしたい場合は以下のようにします
(*po)++;
これでポインタ変数poが指す値がインクリメントされます
#include <stdio.h>
int main()
{
int ary[2] = { 1000 , 2000 };
int *po;
po = &ary[0];
(*po)++;
printf("%d", ary[0]);
return 0;
}