指针数组作为函数参数

7

我有一个关于C/C++中数组和指针的基本问题。

假设我有:

Foo* fooPtrArray[4];

如何将 fooPtrArray 传递给函数? 我已经尝试过:
int getResult(Foo** fooPtrArray){}  //  failed
int getResult(Foo* fooPtrArray[]){} // failed

我该如何处理指针数组?

编辑:我曾经认为出错信息是由于传递了错误的指针数组,但是从所有的回复中我意识到它是其他问题...(指针赋值)

Error msg:
Description Resource Path Location Type incompatible types in assignment of 
`Foo**' to `Foo*[4]' tryPointers.cpp tryPointers line 21 C/C++ Problem

我不太理解为什么它说:Foo* * to Foo*[4]。如果作为函数参数它们可以互换,为什么在赋值时会导致编译错误?

我尝试用最少的代码复制错误消息,如下所示:

#include <iostream>

using namespace std;

struct Foo
{
int id;
};

void getResult(Foo** fooPtrArray)
{
cout << "I am in getResult" << endl;
Foo* fooPtrArray1[4];
fooPtrArray1 = fooPtrArray;
}

int main()
{
Foo* fooPtrArray[4];
getResult(fooPtrArray);
}

1
定义“失败”。是在编译时失败?还是在运行时失败?具体是如何(或模糊不清,我不介意)? - Michael Foukarakis
我将我的修剪代码附在上面,它是编译时错误。错误来自于函数void getResult(Foo* * fooPtrArray)的内部。 - Lily
5个回答

15

两者皆可。

int getResult(Foo** fooPtrArray)

int getResult(Foo* fooPtrArray[])

以及

int getResult(Foo* fooPtrArray[4])

这样做没问题(它们都是等效的)。

从你的问题中并不清楚出了什么问题。是什么“失败”了?

当像这样传递数组时,通常也有意义同时传递元素数量,因为允许数组类型衰减到指针类型的技巧通常特别用于允许传递不同大小的数组:

int getResult(Foo* fooPtrArray[], unsigned n);
...
Foo* array3[3];
Foo* array5[5];
getResult(array3, 3);
getResult(array5, 5);

但是如果你总是传递长度严格为4的数组,使用一个不同类型的指针作为参数可能会是更好的选择:

int getResult(Foo* (*fooPtrArray)[4])
在后一种情况下,函数调用将如下所示。
Foo* array[4];
getResult(&array);

(请注意应用于数组对象的 & 运算符。)

最后,由于这个问题被标记为C++,在后一种情况下也可以使用引用而不是指针。

int getResult(Foo* (&fooPtrArray)[4]);
...
Foo* array[4];
getResult(array);

这看起来很有趣:int getResult(Foo* (*fooPtrArray)[4]),有两个星号和一对括号。这正确吗? - ndim
是的,这是正确的。但在C++中,在这种情况下使用引用(而不是指针)可能更合适(请参见答案中的附加注释)。 - AnT stands with Russia
你能详细说明一下 Foo* (&fooPtrArray)[4] 是如何解析的,以及你将如何在函数体内调用 fooPtrArray 吗? - int3
1
@splicer:在这种情况下,fooPtrArray 是一个指向 Foo 类型的 4 个指针数组的 引用。在函数内部,它将以“通常”的方式使用,例如 fooPtrArray[3] = 0。这与第一组变量没有任何区别,只是数组类型被保留(不会衰减为指针),这意味着您可以执行 sizeof fooPtrArray / sizeof *fooPtrArray 并获得 4 作为结果。同样,此参数仅与 4 元素参数兼容。 - AnT stands with Russia

2
您声明了以下行中的内容:

您用以下代码声明了:

Foo* fooPtrArray[4];

这是一个指向 Foo 对象的指针数组(换句话说,是 Foo* 数组)。

在 C/C++ 中,数组名被定义为指向数组开头的指针。这是因为数组在这些语言中并不是“真正”的类型,而只是内存中特定类型值的连续序列。

在这种情况下,名称为 fooPtrArray 的变量将成为数组中“第一个指针”的指针,即存储指针数组的内存位置的起始点。

因此,你所提出的任何一个函数原型都应该可以工作。但是,在将数组传递给函数时,你总是需要同时传递大小,以便函数知道有多少个元素。所以你应该像这样定义你的方法:

int getResult(Foo** fooPtrArray, int arraySize);

在这个函数中,您可以像这样访问数组中的单个Foo指针(以及随后的Foo对象):

for (int i=0; i < arraySize; i++)
{
    Foo* fooPtr = fooPtrArray[i];
    if (fooPtr)
    {
        fooPtr->memberFunction();
        fooPtr->memberVariable;
    }
}

0

这两个函数签名看起来都应该可以工作。调用函数时,您需要执行以下操作:

int returnValue;
returnValue = getResult(fooPtrArray);

0

0

我不明白这个代码怎么可能没有返回一个int就编译通过了?!

@Kinopiko,你的代码在C++中无法编译通过。

@Lily,你得到了什么错误信息? 在你的例子中,getResult需要返回一个int。这很可能是失败的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接