如何将多维 C 数组传递给函数? [复制]

2024-04-21

我在大学课堂上学习了 C 语言和指针,除了多维数组和指针之间的相似性之外,我认为我已经很好地掌握了这个概念。

我认为由于所有数组(甚至是多维)都存储在连续的内存中,因此您可以安全地将其转换为int*(假设给定的数组是int[]。)但是,我的教授说定义中的星星数量取决于数组中的维数。所以,一个int[]将成为一个int*, a int[][]将成为一个int**, etc.

所以我写了一个小程序来测试一下:

void foo(int** ptr)
{    
}

void bar(int* ptr)
{    
}

int main()
{
    int arr[3][4];

    foo(arr);
    bar(arr);
}

令我惊讶的是,编译器发出了警告both函数调用。

main.c:22:9: warning: incompatible pointer types passing 'int [3][4]' to parameter of type
      'int **' [-Wincompatible-pointer-types]
    foo(arr);
        ^~~
main.c:8:16: note: passing argument to parameter 'ptr' here
void foo(int** ptr)
         ^
main.c:23:9: warning: incompatible pointer types passing 'int [3][4]' to parameter of type
      'int *' [-Wincompatible-pointer-types]
    bar(arr);
        ^~~
main.c:13:15: note: passing argument to parameter 'ptr' here
void bar(int* ptr)
         ^
2 warnings generated.

这里发生了什么?如何更改函数调用,以便其中一个函数可以接受该数组?


My 原问题 https://stackoverflow.com/questions/42430697/what-is-the-pointer-type-of-a-multidimensional-array-when-passed-to-a-function被标记为重复项,由于我不知道如何删除重复项,所以我再次询问它。

Edit:这是not的副本如何将多维数组传递给 C 和 C++ 中的函数 https://stackoverflow.com/questions/2828648/how-to-pass-a-multidimensional-array-to-a-function-in-c-and-c因为我问的是如何更改函数调用本身,而不是函数签名。我知道其中一个函数是正确的,我只是不确定哪一个或如何调用它。

Edit 2:这是我原来问题的重复,但原来的问题被错误地标记为重复,无法得到答复,所以我重新提出。


然而,我的教授说,定义中的星星数量取决于数组中的维数。所以,一个int[]将成为一个int*, a int[][]将成为一个int**, etc.

我真的,really希望你只是误解了他的话,因为那是不正确的。

除非它是操作数sizeof或一元&运算符,or 是用于初始化声明中的字符数组的字符串文字,类型为 " 的表达式N-元素数组T” 将被转换(“衰减”)为“指向的指针”类型的表达式T",表达式的值将是数组第一个元素的地址。如果T是一个数组类型,你最终会得到一个指向数组的指针,而不是指向指针的指针。

通过一些例子:

int arr[10];
...
foo( arr, 10 ); // need to pass number of rows as a separate parameter

在通话中foo, 表达方式arr具有类型“10 元素数组int“。因为它不是sizeof或一元&运算符,它会“衰减”键入int *,表达式的值将是第一个元素的地址。因此,原型为foo将会

void foo( int *arr, size_t rows ); // or int arr[]; it means the same thing in this context

请注意,这与表达式的结果类型相同&arr[0]. arr[0] is an int对象,所以&arr[0]给我们一个int *. IOW, arr == &arr[0].

到目前为止,一切都很好。现在让我们看一个二维数组:

int arr[10][20];
...
foo( arr, 10 );

在这种情况下,表达式arr具有类型“10 元素数组20 元素数组int”;它“衰减”为“指向的指针”类型的表达式20 元素数组int“;因此,原型为foo becomes

void foo( int (*arr)[20], size_t rows ); // or int arr[][20]

记住上面的部分,它说“除非它是......一元的操作数”&运算符”?如果我们写&arr[0], arr[0]具有类型“20 元素数组int“,但确实如此not自动衰减为指针。所以不要获取类型的表达式int **,我们得到一个类型的表达式int (*)[20]。再说一次,arr == &arr[0].

现在让我们看一个 3D 数组:

int arr[10][20][30];
...
foo( arr, 10 );

这次的表情arr具有类型“10 元素数组20 元素数组 30 元素数组int这一次,它“衰减”为“指向的指针”类型的表达式20 元素数组 30 元素数组int”,现在的原型是

void foo( int (*arr)[20][30], size_t rows ); // or int arr[][20][30]

再一次,arr[0]具有数组类型,因此表达式&arr[0]给我们类型int (*)[20][30];再次,arr == &arr[0].

从现在开始,高维数组的模式应该很清楚。

现在,这带来了一个小问题。指向一个的指针N-元素数组与指向数组的指针是不同的类型M- 元素数组,其中N != M。如果你的函数原型是

void foo( int (*)[20], size_t rows );

那么它就会only与...一起工作Nx20 数组;你不能向它传递一个指向具有不同外部维度的数组的指针:

void foo( int (*ap)[20], size_t rows );
...
int arr1[10][20];
int arr2[20][20];
int arr3[20][30];

foo( arr1, 10 ); // okay
foo( arr2, 20 ); // okay
foo( arr3, 20 ); // not okay - arr3 has type int (*)[30], which is not *compatible* 
                 // with int (*)[20]

EDIT

在函数期望的情况下int *并且您有一个多维数组,您将显式传递一个指向第一个元素的指针:

void foo( int *, size_t size );
...
int arr2[10][20];
int arr3[20][10][5];

foo( &arr2[0][0], sizeof arr2 / sizeof arr2[0][0] );
foo( &arr3[0][0][0], sizeof arr3 / sizeof arr3[0][0][0] );
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将多维 C 数组传递给函数? [复制] 的相关文章

  • LINQ to XML - 如何正确使用 XDocument

    现在我首先要说的是 这确实是一项任务 然而 在我遇到 Linq to XML 语法之前 我几乎已经完成了它 我有 2 个课程 曲目和 CD 现在作为作业的一部分 我创建了一张 CD 然后向其中添加了一些曲目 在搜索了大量完美解释了如何从 x
  • 将 2D 数组映射到 1D 数组

    我想用一维数组来表示一个二维数组 函数将传递两个索引 x y 和要存储的值 这两个索引代表一维数组的单个元素 并相应地设置它 我知道一维数组需要具有 arrayWidth arrayHeight 的大小 但我不知道如何设置每个元素 例如 如
  • 测试 hdf5/c++ 中的组是否存在

    我正在打开一个现有的 HDF5 文件来附加数据 我想向那个叫做的小组保证 A存在以供后续访问 我正在寻找一种简单的方法来创建 A有条件地 如果不存在则创建并返回新组 或者返回现有组 一种方法是测试 A存在 我怎样才能高效地做到这一点 根据
  • 为什么C Clock()返回0

    我有这样的事情 clock t start end start clock something else end clock printf nClock cycles are d d n start end 我总是得到输出 时钟周期是 0
  • .NET 可移植类库中的 .ToShortDateString 发生了什么

    我想知道为什么没有 ToShortDateString在 NET 可移植类库中 我有 2 个项目 Silverlight 和常规 NET 类库 使用相同的代码 并且代码涉及调用 ToShortDateString on a DateTime
  • 我应该在单元测试中使用 AutoMapper 吗?

    我正在为 ASP NET MVC 控制器方法编写单元测试 这些控制器依赖于IMapper 我创建的用于抽象 AutoMapper 的接口 使用 Castle Windsor 通过构造函数注入传入 动作方法使用IMapper从领域对象映射到
  • 阅读 Stack Overflow RSS 源

    我正在尝试获取未回答问题的列表the feed https stackoverflow com feeds 但我在阅读时遇到困难 const string RECENT QUESTIONS https stackoverflow com f
  • C中有const吗?

    这个问题可能很幼稚 但是 有没有constC 中的关键字 从哪个版本开始 之间有任何语义和 或句法差异吗const在 C 和 C 中 C 和 C 之间在语法上没有差异const关键字 除了一个相当晦涩的关键字 在 C 中 自 C99 起 您
  • 通过 mpi 发送 c++ std::vector

    我知道存储一个std vector
  • 多维数组将每个列表数组存储在另一个数组中

    我嵌套了可能有 2 或 3 层深度的多维数组 在它里面我可能有也可能没有列表数组 我需要循环数组 Array 0 gt Array id gt 1 name gt cat name 1 list gt Array 1 gt swgdgbdg
  • 为什么以下代码不允许我使用 fgets 获取用户输入但可以使用 scanf?

    这是一个更大程序的简短摘录 但该程序的其余部分无关紧要 因为我认为我能够隔离该问题 我怀疑这与我使用 fgets 的方式有关 我读过 最好使用 fgets 而不是 scanf 但我似乎无法让它在这里正常工作 当我使用以下代码时 程序不会给我
  • C++ Primer 5th Edition 错误 bool 值没有指定最小大小?

    bool 的最小大小不应该是 1 个字节吗 这有点学术性的东西 尽管它们会转换为数字 并且 与其他所有事物一样 它们最终将基本上由计算机内存中的数字表示 但布尔值不是数字 你的bool可以取值true 或值false 即使您确实需要至少 1
  • 使用 Linq 进行异步Where过滤

    我有一个List通过填充的元素async调用 WebService 没问题 我需要过滤该列表以便在应用程序视图上显示某些内容 我试过这个 List
  • 标准 C 中的 sizeof 与 sizeof()? [复制]

    这个问题在这里已经有答案了 我看到一些直接使用 sizeof 的代码 想知道它是否是标准 C 令我惊讶的是 它运行得很好 这是一个例子 include
  • 为什么 C 函数不能返回数组类型?

    我是 C 语言新手 想知道 为什么 C 函数不能返回数组类型 我知道数组名是数组第一个值的地址 而数组是 C 中的二等公民 您自己已经回答了这个问题 数组是二等公民 C 按值返回 数组不能按值传递 因此不能返回它们 至于为什么数组不能按值传
  • 用 C# 编写的带有点击移动的 WPF 游戏

    我试图将标签网格移动到鼠标的位置 就像冒险游戏中的移动一样 理想情况下 我会在途中删除并重新绘制它们 但是 现在我只想弄清楚如何将 int 转换为厚度或 pointtoscreen 到目前为止我有 player XMove int Mous
  • 在 MVVM 中,可以在视图后面的代码中访问 ViewModel 吗?

    在 MVVM 模式中 是否可以接受甚至可以访问视图代码后面的 ViewModel 属性 我有一个可观察的集合 它填充在 ViewModel 中 我需要在视图中使用它来绑定到带有链接列表的无限滚动条 IE private LinkedList
  • 宏观评价[重复]

    这个问题在这里已经有答案了 可能的重复 未定义的行为和序列点 https stackoverflow com questions 4176328 undefined behavior and sequence points 我无法理解以下宏
  • 有没有办法让 VS2010 在我的方法中扩展或收缩 try 块?

    我的代码有很多 try catch finally 块 与我在 VS2010 中的方法不同 除了添加区域之外 我无法在开发时扩展或收缩这些区域来隐藏内容 try vm R vm Qu vm T vm D vm Fil vm Type vm
  • 从 C# 中的 .NET SecureString 读取单个字符?

    WPF 的PasswordBox 返回一个SecureString 它对窥探者隐藏密码 问题是你最终必须获得密码的值 而我在网上找到的建议都涉及将值复制到字符串中 这会让你回到窥探者的问题 IntPtr bstr Marshal Secur

随机推荐

  • jquery悬停图像淡入淡出交换

    我已经在网上搜索了一段时间 试图找到编写 jquery 脚本的最佳方法来完成这个简单的任务 用优雅的淡入淡出效果交换悬停时的图像 我找到了很多解决方案 有些方法很麻烦和笨重 并将其缩小到我认为最好的两个 http designwoop co
  • 属性绑定与属性插值

    我读过一篇关于属性和属性绑定之间差异的文章 据我了解 大多数时候 Angular2 更喜欢属性绑定 因为每次数据更改后 DOM 都会更新 如果我错了 请纠正我 我有一个自定义组件并从父组件中使用它 其中 我有一个 Input named t
  • 在构建 Docker 镜像之前如何对 GitLab 的容器注册表进行身份验证?

    我有一个私有的 GitLab 项目 其中包含用于构建和推送 Docker 映像的管道 因此我必须首先向 GitLab 的 Docker 注册表进行身份验证 Research I read 使用 GitLab CI CD 对容器注册表进行身份
  • 尝试从 Visual Studio 发布 azure 函数时出错

    当我尝试使用 Visual Studio 发布函数时收到以下错误消息 知道如何解决此问题吗 System AggregateException 发生一个或多个错误 gt System Exception 发布遇到错误 我们无法 确定错误原因
  • R:ggplot2 条形图和误差条

    自从新版本的 ggplot2 0 9 3 开始 我在绘制带有误差条的条形图时遇到了问题 所以我有一个像这样的数据框 group N val sd se ci 1 206 3 37 2269533 7 9688645 4 6008261 19
  • 带有 HTML5 音频标签的自定义一键播放器

  • 如何让 Typescript 抛出运行时错误?

    import Component from angular core Component selector app root templateUrl app component html styleUrls app component cs
  • SQL 更新查询 - 聚合可能不会出现在 UPDATE 语句的集合列表中

    我正在尝试编写一个查询 用 HOLIDAY DATE TABLE 中最高的主键值 HID 更新 tbl8 update transactions HID 字段 其中为空 我收到以下错误 聚合可能不会出现在 UPDATE 语句的集合列表中 我
  • MySQL 字符串替换

    我有一列包含 url id url http www example com articles updates 43 http www example com articles updates 866 http www example co
  • 通过样式更改 Android 对话框按钮文本大小

    我正在尝试通过样式放大所有应用程序对话框按钮上的文本大小 以下代码将更改按钮背景颜色 甚至更改文本大小写 但由于某种原因 textSize 项目不受支持
  • 使用soapUI中的Groovy teststep将请求/响应文件存储在本地目录中

    通过soapUI中的常规测试步骤 我希望所有请求和响应文件都存储在具有系统日期的本地目录中 SoapUI 中的常规测试步骤 def name context expand Input TG def locatie context expan
  • jQuery - 从 JSON Stringify 获取值

    我有一个表格 我需要从中获取值 var formConfig JSON stringify bookingform serializeArray 返回如下 name client id value 1 name consignee id v
  • 如何以编程方式访问 Silverlight FrameworkElement 的 ToolTipService?

    我们有一种语言机制 可以在加载 XAML 页面时递归遍历它们 检查每个元素的 Tag 属性 并使用其值来检索要应用于该元素的字符串资源 它目前不支持工具提示 我们必须在每个页面上都有特定的代码才能将语言资源应用于它们 我正在尝试将此功能添加
  • 没有公钥,GitLab 无法克隆公共存储库

    使用亚搏体育appGitLab 6 8 2 我可以以匿名方式克隆公共存储库吗 我的用户命名空间中的存储库标记为public 如果没有在 GitLab 中保存公钥 我就无法克隆它 例如 gt ssh T email protected cdn
  • svn 外部...是或否?

    我在这里读到了一些谴责使用 svn externals 的答案 我确实看到它们如何被滥用 这确实使我们更加依赖 Subversion 但我真的不认为我们的团队会很快放弃它 无论如何 这就是我的困境 我们的解决方案引用了多个项目 这些项目位于
  • 如何将 numpy 数组分成更小的块/批次,然后迭代它们

    假设我有这个 numpy 数组 1 2 3 4 5 6 7 8 9 10 11 12 我想将其分成两批 然后迭代 1 2 3 Batch 1 4 5 6 7 8 9 Batch 2 10 11 12 最简单的方法是什么 EDIT 我很抱歉我
  • 在笑话单元测试角度中显示正确的错误

    我正在 NX 角度工作区中编写单元测试 有时它会给出这样的错误 node 15320 UnhandledPromiseRejectionWarning TypeError Converting circular structure to J
  • 什么是可堆叠修改?

    我读过一本关于 Scala 的书 里面提到了可堆叠修改 using traits 什么是可堆叠修改它们的用途是什么 区分可堆叠修改 无论如何在 scala 中使用该术语 的基本品质是 super 根据特征的混合方式动态受到影响 而一般来说
  • 访问 ctypes 结构中的 np.array

    我有一个带有动态分配数组的 ctypes 结构 即 array 1d double npct ndpointer dtype np double ndim 1 flags CONTIGUOUS class Test Structure fi
  • 如何将多维 C 数组传递给函数? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至是多维 都存储在连续的内存中 因此您可以安全地将其转换为int 假设给定的数组是