1. ホーム
  2. c

[解決済み】ポインタへの代入時に互換性のないポインタ型からの初期化警告が発生した

2022-01-24 22:11:34

質問

このコードを使うと、GCCは「互換性のないポインタ型からの初期化」という警告を出します(コードは問題なく動作し、配列のすべての要素を表示するという、想定されたことを行いますが)。

#include <stdio.h>

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

    printf("%p\n%p\n\n", p);

    for (int a = 0; a < 5; a++)
        printf("%d ", *(p++));
    printf("\n");
}

しかし、次のコードを使用しても警告は表示されません。

int main(void)
{
    int arr[5] = {3, 0, 3, 4, 1};
    int *q = arr;

    printf("%p\n%p\n\n", q);

    for (int a = 0; a < 5; a++)
        printf("%d ", *(q++));
    printf("\n");
}

この2つのスニペットの唯一の違いは、*p = &arr と *q = arr を代入していることです。

  • 正確に言うと、& はどのような違いをもたらすのでしょうか?
  • また、なぜ両方のケースでコードが実行され、まったく同じ出力が得られるのでしょうか?

解決方法は?

  • &arr を与える。 配列ポインタ という特殊なポインタ型 int(*)[5] で、配列全体を指し示す。
  • arr のような式で書かれた場合 int *q = arr; は、最初の要素へのポインタに分解されます。と完全に等価です。 int *q = &arr[0];

最初のケースでは int(*)[5]int* . これらは互換性のないポインタ型であるため、コンパイラの診断メッセージが表示されます。

結局のところ、配列ポインタと最初の要素への int ポインタは同じ表現で、内部的には同じアドレスになる可能性が非常に高いのです。このため、最初の例は正しいC言語ではないにもかかわらず、quot;work"なのです。