哪个定义更好?

std*_*std 5 c

#include<stdio.h>
int main(int argc , char *argv[])
{
    int array[2][2] = {{1,100},{1000,10000}};

    int *pointer    = array;
    int *ppointer   = &array;
    int *pppointer  = array[0];
    int *ppppointer = &array[0];

    printf("%d\n",*pointer);
    printf("%d\n",*ppointer);
    printf("%d\n",*pppointer);
    printf("%d\n",*ppppointer);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

四个指针指向数组的第一个元素.上面显示的哪个定义更好?我不知道为什么数组和数组的值相同?

AnT*_*AnT 8

所有定义编译的唯一原因是你的C编译器在指针类型转换方面过于允许.如果你使用一些在这方面使它更迂腐的开关,它应该立即告诉你只有第三次初始化是有效的,而其余的是错误的.

在大多数情况下(少数例外),当T[N]在表达式中使用类型数组时,它会"衰减"(被隐式转换)为指针类型T *- 指向其第一个元素的指针.换句话说,在任何数组的上下文中A,A表达式相当于&A[0].数组类型衰减不发生的唯一上下文是一元运算&符,sizeof运算符和字符串文字,用作char数组的初始值设定项.

在您的示例中arrayint [2][2]type 的值.当在初始化的右侧使用时,它会衰减到指针类型int (*)[2].因此,这是无效的

int *pointer    = array;
Run Code Online (Sandbox Code Playgroud)

右边是int (*)[2],而左边是int *.这些是不同的指针类型.你不能用另一个初始化一个.

int *ppppointer = &array[0];
Run Code Online (Sandbox Code Playgroud)

完全等同于前一个:右侧产生int (*)[2]类型的值.由于同样的原因,它是无效的.

&array表达式生成一个int (*)[2][2]类型的指针.再次,出于这个原因

int *ppointer   = &array;
Run Code Online (Sandbox Code Playgroud)

是无效的.

您的示例中唯一有效的初始化是

int *pppointer  = array[0];
Run Code Online (Sandbox Code Playgroud)

array[0]是一个int [2]类型的表达式,它衰减为int *类型 - 与左侧相同的类型.

换句话说,这里没有哪个"更好".只有一个初始化有效,其他初始化是非法的.有效的初始化也可以写成

int *pppointer  = &array[0][0];
Run Code Online (Sandbox Code Playgroud)

由于我上面描述的原因.现在,哪个右侧"更好"(array[0]&array[0][0])是您个人喜好的问题.


为了使您的其他初始化有效,指针应声明如下

int (*pointer)[2]     = array;
int (*ppointer)[2][2] = &array;
int (*ppppointer)[2]  = &array[0];
Run Code Online (Sandbox Code Playgroud)

但是这样的指针将具有与指针不同的语义int *.你显然需要int *特别的.