1. ホーム
  2. C

C 言語のポインタ配列のポインタ型、ポインタに値を割り当てるために配列名を使用、コンパイル時の警告:互換性のないポインタ型からの初期化

2022-02-10 23:37:49

参考文献[1]参照  http://blog.chinaunix.net/uid-30254479-id-5066996.html

0. 質問

配列名を持つポインタの代入 警告:互換性のないポインタ型からの初期化

コード例は以下の通りです。

int a[5]={1,2,3,4,5};
int (*p)[5]= a;

コンパイル時の警告: 互換性のないポインタ型からの初期化。

以下のようにコードを修正すると、警告は消えます。

int a[5]={1,2,3,4,5};
int (*p)[5]= &a;

理由
とはいえ a と &a は同じ値で,どちらも配列の先頭アドレスですが,型は同じではありません :
アドレスとしてのaはint *型である。
&a のアドレスは int (*)[5] 型である。
で、pもint型(*)[5]である。

1. バリデーション

#include<stdio.h>

int main(void)
{
        int a[5] = {1,2,3,4,5};
        int (*p)[5] = &a;

        printf("a = %p\n", a);
        printf("&a = %p\n", &a);
        printf("p = %p\n", p);
        printf("p+1 = %p\n", p + 1);

        int b[] = {1,2,3,4,5};
        int c[][3] = {
{1,2,3},{4,5,6}};

        return 0;
}

出力してください。

a = 0xffffef350420
&a = 0xffffef350420
p = 0xffffef350420
p+1 = 0xffffef350434

int (*p)[5] = &a;

p は5個の要素を持つ1次元配列へのポインタ型です。

p++、またはp+1は、"5つの要素を含む1次元配列a"の後のアドレスを指すことになります。

int a[5] = {1,2,3,4,5} です。

int *p = a; // equivalent to int *p = a[0]; pはint型へのポインタ、p++は配列の次の要素である2のアドレスを指します。

int (*p)[5] = &a; // 1次元配列ポインタpは、1次元配列a全体を指す。 p++で、"5つの要素を含む1次元配列a"の後のアドレスを指すようになります。

つまり、2次元の配列を定義するということは、2次元目の長さを指定することです。

もし

int c[][] = {
{1,2,3},{4,5,6}};

というコンパイルエラーが発生します。

c_pointer_type.c: In function 'main':
c_pointer_type.c:14:6: error: array type has incomplete element type
  int c[][] = {
{1,2,3},{4,5,6}};
      ^