You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

二维数组与指针声明的区别及相关C代码编译异常疑问

二维数组与双指针的类型兼容问题解析

先看你给出的代码:

int main()
{
    int arr[][3] = {1,2,3,4,5,6};
    int **p= &arr;
    printf("%u %u" , *p, *(p+1));

    return 0;
}

为什么会出现类型兼容错误?

这是&arr的类型和int**完全不匹配导致的:

  • 定义的arr是2行3列的二维数组,类型为int[2][3],所以&arr的类型是int(*)[2][3]——这是一个指向整个二维数组的指针。
  • 而int**是指向int*类型变量的指针,它和int(*)[2][3]属于完全不同的类型体系,标准C不允许这种隐式类型转换,严格的编译器会直接抛出类型不兼容的错误。

为什么部分编译器会输出1和4?

那些输出结果的编译器是做了非标准的隐式类型转换,但这种行为属于未定义行为,完全依赖于内存布局和编译器实现:

  • 二维数组arr在内存中是连续存储的:1,2,3,4,5,6依次排列。
  • 当&arr被强制转换成int**后,*p会把arr起始地址处的4字节(假设是32位系统,int占4字节)当作int*的取值来读取,而这4字节正好是数组第一个元素1的数值。
  • *(p+1)则是让p跳过一个int*的长度(同样是4字节),读取接下来的4字节,也就是数组的第四个元素4的数值。
  • 这种操作完全是巧合,换个系统或编译器就可能出现崩溃、乱码等其他结果,绝对不能依赖。

双指针为什么不能指向二维数组的第一个元素?

二维数组的第一个元素是arr[0],它是一个包含3个int的一维数组,类型为int[3]。指向它的指针应该是int(*)[3](指向一维数组的指针),而不是int**:

  • int**指向的是一个存储了int*指针的变量,但二维数组在内存里并没有存储任何指针,只是连续的int元素。
  • 如果你想用指针操作二维数组,正确的写法应该是:
int main()
{
    int arr[][3] = {1,2,3,4,5,6};
    int (*p)[3] = arr; // p是指向包含3个int的一维数组的指针
    printf("%d %d", *(*p), *(*(p+1))); // 输出1 4
    // 或者更直观的写法:printf("%d %d", p[0][0], p[1][0]);
    return 0;
}

内容的提问来源于stack exchange,提问作者Bhargav Patil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:02:46