C语言动态分配矩阵:为何f(b)、g(b)调用不合法?
为什么静态二维数组不能传给
int**或int*[]类型的函数? 这个问题的核心在于C语言中静态二维数组的类型和int**/int*[]本质上完全不同,别被它们看起来相似的写法给误导了,咱们一步步拆解:
1. 先搞清楚静态二维数组int b[2][3]的真实类型
当你定义int b[2][3]时,它并不是一个“指针的指针”或者“指针数组”,而是一个包含2个元素的数组,每个元素又是一个包含3个int的数组。
在函数调用时,数组会自动退化为指向其第一个元素的指针,所以b退化成的指针类型是int (*)[3]——也就是“指向包含3个int的数组的指针”,而不是int**。
2. 分析f(int** p)和g(int* p[])的参数类型
- 对于
f(int** p):int**表示的是指向int*类型变量的指针。它指向的应该是一个存储着int*指针的内存位置(比如一个int*数组的首地址)。 - 对于
g(int* p[]):这里要注意一个C语言的关键规则——函数参数中的数组声明会自动退化为指针。所以int* p[]实际上等价于int** p,和f的参数类型完全一样。
因为b退化成的int (*)[3]和int**是完全不兼容的类型,编译器无法完成隐式转换,所以调用f(b)和g(b)会触发非法报错。
3. 为什么h(int p[2][3])是合法的?
同样应用函数参数数组退化为指针的规则,int p[2][3]在函数参数中会被解析为int (*p)[3]——也就是“指向包含3个int的数组的指针”,这刚好和b退化成的指针类型完全匹配,所以h(b)可以合法调用。
额外提醒:别轻易强制转换
你可能会想“那我强制转换成int**行不行?”,比如f((int**)b)。虽然编译器可能不会报错,但这是非常危险的行为:
- 静态二维数组的内存是连续的,所有元素挨在一起存储;
- 而
int**指向的通常是一个指针数组,每个指针指向单独的一行(每行内存可能不连续)。
强制转换后访问内存会导致未定义行为,绝对不推荐这么做。
内容的提问来源于stack exchange,提问作者HereBeeBees
相关产品推荐
相关产品推荐

