C++将数组指针作为函数参数传递

46

我正在尝试使用数组指针作为函数参数来生成一个数组。

void generateArray(int *a[],  int *si){
  srand(time(0));
  for (int j=0;j<*si;j++)
       *a[j]=(0+rand()%9);
} //end generateArray;

int main() {
  const int size=5;
  int a[size];

  generateArray(&a, &size);

  return 0;
} //end main

但当我编译它时,会出现以下消息:

cannot convert `int (*)[5]' to `int**' for argument `1' to `void generateArray(int**, int*)'

5
有几个问题需要指出来 - 首先,不要通过引用传递一个 const int,而是通过值传递。其次,调用:generateArray(a, sizeof(a)/sizeof(a[0]))。这种写法比较啰嗦,但在处理数组时是标准最佳实践。 - djechlin
3
еҰӮжһңиҝҷжҳҜC++пјҢжңҖеҘҪдҪҝз”Ёstd::vectorжҲ–std::arrayпјҡе®ғ们еңЁдј йҖ’еҲ°еҮҪж•°ж—¶д»Қ然зҹҘйҒ“иҮӘе·ұзҡ„еӨ§е°ҸгҖӮ - moooeeeep
只要您将参数定义为std::vector<int>&std::array<int>&(或更可能的是,将generateArray定义为模板函数并使用T&作为参数类型); 如果您直接从int a[]转换为std::array<int, 5>(或与std::array<int, 5>一起使用的模板化的T),则会通过值传递(复制您不想复制的内容,对副本进行操作,并使main中的a保持不变)。 - ShadowRanger
@ShadowRanger这实际上是另一个好处,因为如果函数参数需要修改数组元素,你可以清晰地看到。 - moooeeeep
5个回答

100

您过于复杂化了 - 它只需要是这样:

void generateArray(int *a, int si)
{
    for (int j = 0; j < si; j++)
        a[j] = rand() % 9;
}

int main()
{
    const int size=5;
    int a[size];

    generateArray(a, size);

    return 0;
}

当你将数组作为参数传递给函数时,它会衰减为指向数组第一个元素的指针。因此通常不需要传递指向数组的指针。


2
我知道这会使整个代码过于复杂,但这样做的目的是使用指针。 - Ortharios
14
@Ortharios:这是使用指针。因为在语言设计上出现了错误,当int a[]作为函数参数时,实际上是int* a。你会看到Konrad在dashblinkenlight的回答下面反对这种令人困惑的语法,我完全同意。 - Benjamin Lindley
2
如果这能让你更满意,我已经更改了 generateArray 的声明,使其现在采用显式指针。它仍然是相同的函数签名,因此这只是一种外观上的变化,但希望现在它满足“使用指针”的要求了? - Paul R
2
在我看来,显式地将其声明为指针会使代码的含义变得不太清晰-在一种情况下,您确定正在使用数组,在另一种情况下,您只是被告知它是一个指针,您需要记住它是一个数组。出于这个原因,我会将答案恢复到其原始解决方案。 - Super Cat
1
@SuperCat:我同意 - 代码应该尽可能地表达意图,而指针总是有些模糊不清。然而,这似乎是一种无聊的家庭作业任务,目标是按照指示去做而不是做最好的事情。 - Paul R

25

在函数参数中使用 int *a[](但不是在普通声明中),它是指向指针的指针,而不是指向数组的指针(在普通声明中,它是指针数组)。指向数组的指针看起来像这样:

int (*aptr)[N]

其中N是一个特定的正整数(不是变量)。

如果你把你的函数设为模板,你就可以这样做,而且你甚至不需要传递数组的大小(因为它会自动推断):

template<size_t SZ>
void generateArray(int (*aptr)[SZ])
{
    for (size_t i=0; i<SZ; ++i)
        (*aptr)[i] = rand() % 9;
}

int main()
{    
    int a[5];    
    generateArray(&a);
}

你也可以参考:

template<size_t SZ>
void generateArray(int (&arr)[SZ])
{
    for (size_t i=0; i<SZ; ++i)
        arr[i] = rand() % 9;
}

int main()
{    
    int a[5];    
    generateArray(a);
}

7
+1,但是请注意模板解决方案会带来负面影响,即为每个在此处使用的数组大小生成一个函数。 - David Rodríguez - dribeas

7

当您将数组传递给生成数组的函数时,不需要取指向该数组的指针,因为数组已经在传递到函数时 衰变为指针。只需将参数设为int a[],并在函数内部像使用常规数组一样使用它,更改将应用于您传递的数组。

void generateArray(int a[],  int si) {
    srand(time(0));
    for (int j=0;j<*si;j++)
        a[j]=(0+rand()%9);
}

int main(){
    const int size=5;
    int a[size];
    generateArray(a, size);
    return 0;
}

作为附注,您不需要通过指针传递大小,因为您在函数内部没有更改它。此外,将指向常量的指针传递给期望指向非常量的参数是不明智的。

2
在我看来,将参数声明为x[]只会产生误导。为什么不明确表明它是一个指针呢? - Konrad Rudolph
1
@KonradRudolph 我同意,使用指针是一种“更诚实”的语法。但由于OP使用了空方括号语法,我决定继续使用它。 - Sergey Kalinichenko

0

我猜这会有所帮助。

当作为函数参数传递时,数组的行为与指针相同。因此,您不需要引用它们。只需键入: int x[]int x[a] 。两种方式都可以。我猜这就是Konrad Rudolf所说的,早就想到了。


-1
This is another method . Passing array as a pointer to the function
void generateArray(int *array,  int size) {
    srand(time(0));
    for (int j=0;j<size;j++)
        array[j]=(0+rand()%9);
}

int main(){
    const int size=5;
    int a[size];
    generateArray(a, size);
    return 0;
}

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