假设arr是一个int型数组,为什么int (*p)[4]=arr报错initialization of ‘int (*)[4]‘ from incompatible pointer type ‘i‘

数组名在大多数情况下会退化为指向其首元素的指针。一维数组会退化指向数组第一个元素的地址,二维数组会退化指向第一行的指针。

目录

一、一维数组

1.数组名的类型 

2.int (*p)[4] 的类型

3.错误原因分析 

4.正确写法如下 

 二、二维数组

1.二维数组实质 

2.数组名的退化规则

3.退化目的:简化多维访问

4.示例代码:


一、一维数组

1.数组名的类型 

假设arr声明为:

int arr[N];     //N是数组长度,例如N=4
  •  数组名 arr 在大多数情况下会退化为指针,指向数组第一个元素的地址,即 arr 的类型是 int*
  • 例外情况:当 arr 与 & 或 sizeof 运算符结合时,数组名保留完整的数组类型信息。例如:

        ①&arr 的类型是 int (*)[N](指向长度为N的数组的指针)。

        ②sizeof(arr)返回整个数组的字节大小( N*sizeof(int) )。

2.int (*p)[4] 的类型

int (*)[4] 是一个指向长度为4的整型数组的指针,即:

  • p的类型是 int (*p)[4]。
  • p指向的是一个数组整体,而不是数组中的某个元素。
  • 对 p 解引用(*p)会得到一个长度为4的整型数组(类型为int [4])。

3.错误原因分析 

假设 arr 是一个普通的 int 型数组(例如 int arr[4];):

int (*p)[4]=arr;    //错误!!!
  • 类型不匹配:

        ①arr 退化为 int*(指向单个 int 元素的指针)。

        ②p的类型是 int (*)[4](指向长度为4的整型数组的指针)。

        ③int* 与 int (*)[4]是两种完全不同的指针类型,直接赋值会导致编译器报错。

  • 报错信息如下:
warning: initialization of 'int (*)[4]' from incompatible pointer type 'int *' [-Wincompatible-pointer-types]
    9 |     int (*p)[4]=arr;

4.正确写法如下 

#include 
#include 
 
int main(int argc, char const *argv[])
{
    // 定义一个包含4个整数的数组,并初始化
    int arr[4]={1,2,3,4};
    // 定义一个指向包含4个整数的数组的指针,并将数组arr的地址赋给它
    int (*p)[4]=&arr;
    // 使用for循环遍历数组并打印每个元素
    for (int i = 0; i < 4; i++)
    {
        printf("%d",(*p)[i]);
    }
     
    // 返回0表示程序成功结束
    return 0;
}

 二、二维数组

1.二维数组实质 

        在C语言中,二维数组退化为指针的行为是由其底层设计决定的,目的是简化多维数组的操作并保持语法一致性。

  • 二维数组 int arr[m][n] 本质上是一维数组的数组

        ①它包含m个元素,每个元素本身是一个长度n的一维数组。

        ②内存中按 行优先 连续存储,所有元素紧密排列。 

2.数组名的退化规则

在大多数表达式中,数组名会退化为指向其第一个元素的指针:

  • 一维数组:int arr[5] -> arr 退化为 int*(指向 arr[0] )。
  • 二维数组:int arr[3][4] -> arr 退化为 int (*)[4](指向 arr[0],即第一个长度为4的子数组)。

3.退化目的:简化多维访问

  • 二维数组的每个元素是一个子数组(如 arr[0] 是 int[4])。
  • 通过退化为指向子数组的指针,可以直接用指针算数访问行:(数组下标从0开始)

                arr+i 指向第 i 行(即arr[i]),解引用*(arr+i)得到第 i 行的首地址。

  • 这使得 arr[i][j] 的语法等价于 *(*(arr+i)+j),保持直观的多维访问。

4.示例代码:

#include 

int main() {
    // 定义一个3行4列的二维数组
    int array[3][4] = {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
    };
    // 指针ptr 指向包含4个整数的数组的,
    //array 指向二维数组的第一个一维数组
    int (*ptr)[4] = array;
    // 遍历二维数组的每一行
    for (int i = 0; i < 3; i++) {
        // 遍历当前行的每一个元素
        for (int j = 0; j < 4; j++) {
            // ptr[i] 表示指向 array 中第 i+1 个一维数组的指针(因为数组索引从0开始),
            //而 *(ptr[i] + j) 则是通过这个指针访问该一维数组中的第 j+1 个元素。
            printf("array[%d][%d] = %d\n", i, j, *(ptr[i] + j));
        }
    }

    return 0;
}

你可能感兴趣的:(C/C++,c语言,c++)