c - 通过指向不完整数组类型的指针将多维数组传递给没有最大大小的函数

标签 c c11

据我所知,数组总是作为指针传递。例如声明:

void foo(int array[2][5]);

对于编译器来说意味着完全一样的东西:

void foo(int (*array)[5]);

你可以说这两种形式是等价的。现在,我想知道为什么允许将其声明为:

void foo(int (*array)[]);

虽然不是:

void foo(int array[][]);

举个例子:

#include <stdio.h>

void foo(int (*p)[3]);
void bar(int (*p)[]);

int main(void)
{
    int a[2][3] = {{1, 2, 3}, {4, 5, 6}};

    foo(a);
    bar(a);

    return 0;
}

// The same as int p[][3] or int p[N][3] where N is a constant expression
void foo(int (*p)[3]) 
{

}

// Would it the same as int p[][] or int p[N][] (by analogy)?
void bar(int (*p)[])
{

}

它编译正常并且没有警告,但是如果我将 bar 的声明更改为:

void bar(int p[][]);

那么这是一个错误。

为什么 C 允许这种“晦涩”的方式来传递数组?

最佳答案

数组不是指针,如果你声明一个未指定大小的指针数组也没关系,因为它会连续存储指针中存储的地址,并且每个元素的大小是已知的,但是 p[][] 要求数组是连续的,而不是它们的地址,并且数组的大小是未知的,所以这就是问题所在。

为了清楚起见,如果你说 int p[][] 你不知道 p[0]p[1 有多远] 而在 int (*p)[] 中,您知道距离是指针的大小。

数组被转换为指针,但不是指针。

关于c - 通过指向不完整数组类型的指针将多维数组传递给没有最大大小的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31438122/

相关文章:

用于数值积分的 C 代码在一台计算机上运行但在另一台计算机上崩溃

c - 在标准 C 中从头开始实现 memcpy 在技术上是不可能的吗?

c - 枚举值是在预处理时还是在编译时解析的?

c - 为什么编译器不给出冲突错误?

c - C中的递归冒泡排序

c - c 如何让函数声明具有任意参数类型?

c++ - 如何理解独立 C 或 C++ 实现中的原子?

c - 通过来自其他结构成员的偏移指针访问结构成员是否合法?

c - 在 C11 之后是否有任何 future C 标准的计划?

c - fwrite 是否可以写入一些字节但返回零?