配列とポインタ

社内の勉強会用のネタ資料を作っていたんだけどはてなをたぐっていると似たようなネタがあったのでTBしてみる。

  • 「式の中では」配列名はその配列の先頭要素をさすポインタと同意(※例外あり)
  • 例外の場合を除けば、有効な領域を指しているポインタは配列と同じように使うことができる。というか同じように使えるようにCの文法が決められているといった方が正しいか?!

[]演算子

ポインタpと整数iに対して[]演算子を次のように定義する(構文糖/シンタックスシュガー)
p[i] ≡ *(p + i)

式中(宣言以外のところで)で配列名はその先頭要素を指すポインタとして振る舞う(例外あり)

   int array[10];
   array → &array[0]

式中で配列名がその先頭要素を指すポインタと振る舞いが異なる例外ケース

  • &のオペランドになった場合
    • 配列:配列全体を指すポインタ
    • ポインタを指すポインタ
  • sizeofのオペランドになった場合
    • 配列:配列全体のサイズ
    • ポインタ:ポインタ変数のサイズ
  • char配列がchar配列の初期化子になった場合
  • 配列名は左辺値になれない

配列名と型

宣言int array[10];がある場合の次の違い

  1. array
  2. &array[0]
  3. &array

値はすべて同じ
(1)と(2)は全く同意
(3)だけ型が違う(int (*)[10]となる (1)(2)の型はint *)


ついでにポインタについてこんな風に説明しているサイトがあった。
http://www.kis-lab.com/serikashiki/C/C06.html
「int型のポインタ」とか言うのがまずいと思う。型名は単に宣言から識別子を抜けばよいのでint*でありintを指すポインタ型とかintのポインタ型と表現するのが妥当であろう。

NULLポインタ、void型のポインタ(←って何?と一瞬思った。void*のことなのだろうね)もかなり怪しい。

配列とポインタの違い

次の宣言の違いがメモリ配置とともに説明できれば配列とポインタの理解は大丈夫だろう。

  • int a[3][7];
  • int a[7][3];
  • int *a[3];
  • int (*a)[3];
  • int **a;