通过引用在C中传递数组?


70

如何在C中通过引用传递结构数组?

举个例子:

Answers:


139

在C语言中,数组作为指向第一个元素的指针传递。它们是唯一未真正按值传递的元素(指针按值传递,但未复制数组)。这允许被调用的函数修改内容。

现在,如果要更改数组本身(元素数...),则无法使用堆栈或全局数组来执行此操作,只能使用堆中动态分配的内存来执行。在这种情况下,如果要更改指针,则必须将指针传递给它:

在问题编辑中,您专门询问有关传递结构数组的问题。您有两种解决方案:声明一个typedef,或明确声明您正在传递一个struct:

您可以在声明类型时键入typedef(这是C语言中的常见用法):


2
使用memset(array,0,sizeof array); 而不是在重置内部进行for()循环:)
rodi 2012年

5
@rodi:考虑到您引入了一个错误,这很有趣:)我已经更新了要使用的代码,memset因为应该使用它:memset(array,0,size * sizeof *array)-sizeof(array)在这种情况下是指针的大小,而不是指针的数据。
大卫·罗德里格斯(DavidRodríguez)-dribeas 2012年

1
这是好习惯 不要键入强制类型转换malloc的返回值。看到这里
Aka

2
@Aka:你是绝对正确的,我已经了解到,因为我这个大约900年前写:) [我已经编辑去除石膏,感谢提出这个问题]
大卫·罗德里格斯- dribeas

当将数组类型限制为int时,为什么选择sizeof(* array)?为什么不只是sizeof(int)?
Elias Hasle

12

在这里扩展一些答案...

在C语言中,当数组标识符作为&或sizeof的操作数出现在上下文之外时,标识符的类型隐式地从“ T的N个元素数组”转换为“指向T的指针”,其值为隐式设置为数组中第一个元素的地址(与数组本身的地址相同)。这就是为什么当您仅将数组标识符作为函数的参数传递时,该函数会接收指向基本类型而不是数组的指针。由于仅通过查看指向第一个元素的指针就无法确定数组的大小,因此必须将大小作为单独的参数传递。

有几种将数组传递给函数的替代方法。

有一个指向T数组的指针,而不是指向T的指针。您可以将这样的指针声明为

在这种情况下,p是指向T的N元素数组的指针(与T * p [N]相对,其中p是指向T的N元素数组)。因此,您可以将指针传递给数组,而不是将指针传递给第一个元素:

此方法的缺点是数组大小是固定的,因为指向T的10个元素的数组的指针与指向T的20个元素的指针的类型不同。

第三种方法是将数组包装在结构中:

这种方法的优点是您不必操弄指针。缺点是数组大小是固定的(同样,T的10个元素的数组与T的20个元素的数组是不同的类型)。


包装方法的另一个缺点wrapper是按价值传递。80个字节(-ish),内部的赋值SomeMethod()对中wrapper声明的内容无效main。看起来像个错误。
bobbogo 2015年

9

C语言不支持任何类型的引用传递。最接近的等效项是将指针传递给该类型。

这是两种语言的人为例子

C ++样式API

等效的C


我知道,但是我发现使用相同方法传递数组的问题是:s
Hannoun Yassir

3
@Yassir,你能举个例子吗?
JaredPar

这个例子演示了通过引用传递基本类型(使用通过值传递的指针),但是没有演示通过引用传递结构体数组,如下面的文章中正确演示的。
拉尔夫·卡拉维奥

我的意思是在dribeas的帖子中正确演示了!=)
拉尔夫·卡拉维奥

@Ralph,您认为它值得-1吗?OP提出了一个没有有效答案的问题,我提供了一个简单的“最近的功能是...”答案。也许不是+1答案,但肯定不是-1
JaredPar

7

还应注意,如果要在方法中创建数组,则无法返回它。如果返回指向它的指针,则该函数返回时,该指针将从堆栈中删除。您必须将内存分配到堆上并返回指向该堆的指针。例如。


6

在普通C语言中,您可以在API中使用指针/大小组合。

使用指针最接近C中可用的按引用调用。


6

默认情况下,数组通过引用有效地传递。实际上,传递第一个元素的指针的值。因此,接收此信息的函数或方法可以修改数组中的值。

这两个调用是等效的,并且退出值应为0;否则为0。


2

大家好,这是一个简单的测试程序,该程序演示了如何使用new或malloc分配和传递数组。只需剪切,粘贴并运行它。玩得开心!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.