C 数组指针编译时警告:警告:从不兼容的指针类型初始化

C 数组指针编译时警告:警告:从不兼容的指针类型初始化,c,arrays,pointers,C,Arrays,Pointers,使用涉及阵列点的简单示例会生成以下警告。代码的编译和执行也会引发问题 这是整数数组。 整数[3]={101,202,303} 这两个调用生成警告 int *p2 = &numbers; int **p3 = &numbers; 以下是生成的警告 > cc -o myApp test.c test.c: In function 'main': test.c:9:12: warning: initialization from incompatible

使用涉及阵列点的简单示例会生成以下警告。代码的编译和执行也会引发问题

这是整数数组。 整数[3]={101,202,303}

这两个调用生成警告

    int *p2 = &numbers;
    int **p3 = &numbers;
以下是生成的警告

 > cc -o myApp test.c
 test.c: In function 'main':
 test.c:9:12: warning: initialization from incompatible pointer type [enabled by default]
 int *p2 = &numbers;
        ^
 test.c:10:13: warning: initialization from incompatible pointer type [enabled by default]
 int **p3 = &numbers;
         ^
使用的代码如下所示:

#include <stdio.h>

int main ()
{
    int numbers[3] = { 101, 202, 303};
    int size = sizeof(numbers) / sizeof (numbers[0]);

    int *p = numbers;
    int *p2 = &numbers;
    int **p3 = &numbers;
    int *p4 = &numbers[0];

    int *end = p + size;

    printf("p           = 0x%d\n", p);
    printf("p2          = 0x%d\n", p2);
    printf("p3          = 0x%d\n", p3);
    printf("numbers     = 0x%d\n", numbers);
    printf("&numbers    = 0x%d\n", &numbers);
    printf("numbers[0]  = 0x%d\n", numbers[0]);
    printf("&numbers[0] = 0x%d\n", &numbers[0]);

    for (; p != end; p++)
    {
            printf ("0x%d\n", p);
    }
}
p2和p3以及p都指向同一地址。 我真的认为使用p3作为双指针可以解决警告问题,但似乎没有。 为什么p2和p3会生成警告?它想说什么?

应该是这样的

int numbers[3] = { 101, 202, 303};

成员的访问方式应如下所示

(*p2)[0],(*p2)[1] and (*p2)[2]
这与

*(*(p2)+0),*(*(p2)+1) and *(*(p2)+2)
而且

p2[0][0],p2[0][1] and p2[0][2] // Since array notation can be used to dereference pointers.
应该是的

int numbers[3] = { 101, 202, 303};

成员的访问方式应如下所示

(*p2)[0],(*p2)[1] and (*p2)[2]
这与

*(*(p2)+0),*(*(p2)+1) and *(*(p2)+2)
而且

p2[0][0],p2[0][1] and p2[0][2] // Since array notation can be used to dereference pointers.

我明白了让你感到困惑的原因。你第一次看到

 int *p = numbers;
不要认为
数字
是指针类型。它只是一个数组对象(
int[3]
),它被转换成指向它的第一个元素的指针,即
int*
。这称为阵列衰减

现在您可以在
int**p3=&numbers-
&数字
将为
int**
类型

这就是诀窍所在-数组衰减在某些情况下不会发生-当数组用作
&
运算符的操作数时-那么它就是这样一种情况-所以它不会衰减。它将是一个数组对象,其指针被认为是
int(*)[3]

有了这个逻辑,
int*p2=&numbers
编译器也会抱怨。正确的答案应该是这里所说的
int(*pp)[3]=&numbers
。请注意,打印指针(不是函数指针)使用
%p
格式说明符,参数转换为
void*

编译器试图警告您指针类型不匹配。(对于指针,它所指向的类型很重要,因为指针算术由该类型决定)

从§

除非它是
sizeof
运算符的操作数、
\u Alignof
运算符或一元
&
运算符的操作数,或者是用于初始化数组的字符串文字,否则类型为“array of type”的表达式将转换为类型为“pointer to type”的表达式它指向数组对象的初始元素,不是左值


我明白了让你感到困惑的原因。你第一次看到

 int *p = numbers;
不要认为
数字
是指针类型。它只是一个数组对象(
int[3]
),它被转换成指向它的第一个元素的指针,即
int*
。这称为阵列衰减

现在您可以在
int**p3=&numbers-
&数字
将为
int**
类型

这就是诀窍所在-数组衰减在某些情况下不会发生-当数组用作
&
运算符的操作数时-那么它就是这样一种情况-所以它不会衰减。它将是一个数组对象,其指针被认为是
int(*)[3]

有了这个逻辑,
int*p2=&numbers
编译器也会抱怨。正确的答案应该是这里所说的
int(*pp)[3]=&numbers
。请注意,打印指针(不是函数指针)使用
%p
格式说明符,参数转换为
void*

编译器试图警告您指针类型不匹配。(对于指针,它所指向的类型很重要,因为指针算术由该类型决定)

从§

除非它是
sizeof
运算符的操作数、
\u Alignof
运算符或一元
&
运算符的操作数,或者是用于初始化数组的字符串文字,否则类型为“array of type”的表达式将转换为类型为“pointer to type”的表达式它指向数组对象的初始元素,不是左值


首先,始终使用
%p
打印指针值:

printf( "%p\n", (void *) p );
printf( "%p\n", (void *) p1 );
根据声明

int numbers[3];
那么以下是正确的:

Expression        Type        "Decays" to         Value
----------        ----        -----------         -----
   numbers        int [3]     int *               Address of first element of array
  &numbers        int (*)[3]  n/a                 Address of array (which is the same as above)
  *numbers        int         n/a                 Value of numbers[0]
除非它是
sizeof
或一元
&
运算符的操作数,或者是用于初始化声明中字符数组的字符串文字,否则类型为“array of
T
”的表达式将转换(“decay”)为类型为“pointer to
T
”的表达式,表达式的值将是数组第一个元素的地址。因此,在大多数情况下(如赋值的RHS或函数的参数),表达式
numbers
的类型为
int*

那么如何正确初始化
p2
p3
?这取决于编写
p2+1
p2[1]
p3+1
p3[1]
时希望发生什么。如果希望
p2+1
指向
numbers
中的第二个元素,或者希望
p2[1]
等于
numbers[1]
,则可以编写

int *p2 = numbers;
int (*p2)[3] = &numbers;
如果希望
p2+1
指向
numbers
数组末尾后面的
int
的下一个3元素数组,则可以编写

int *p2 = numbers;
int (*p2)[3] = &numbers;
然后将
p3
初始化为

int **p3 = &p2;

基于
p2
的声明方式

一张照片可能会有帮助。假设以下声明:

int numbers[3] = { 0, 1, 2 };
int *p0 = numbers;
int (*p1)[3] = &numbers;
然后事情看起来是这样的:

         +---+                    
numbers: | 0 | numbers[0] <------ p0, p1
         +---+                    
         | 1 | numbers[1] <------ p0 + 1
         +---+
         | 2 | numbers[2]
         +---+
          ...             <------ p1 + 1
+--+

数字:| 0 |数字[0]首先,始终使用
%p
打印指针值:

printf( "%p\n", (void *) p );
printf( "%p\n", (void *) p1 );
根据声明

int numbers[3];
那么以下是正确的:

Expression        Type        "Decays" to         Value
----------        ----        -----------         -----
   numbers        int [3]     int *               Address of first element of array
  &numbers        int (*)[3]  n/a                 Address of array (which is the same as above)
  *numbers        int         n/a                 Value of numbers[0]
除非它是
sizeof
或一元
&