19

考虑:

int sum(const int numbers[], const int size){
    if (size == 0)
        return 0;
    else
        return numbers[0] + sum(numbers+1, size-1);
}

这是一个来自 MIT 6.096 的简单递归函数,用于添加任意数量的整数,并且它可以工作。

我无法理解的是最后一行:

numbers+1给定numbers[]一个int数组,你不应该将整数添加到int[]常量中,它是如何工作的?

4

5 回答 5

21

how does "numbers+1" work, given numbers[] is an int array and you shouldn't be able to add an integer to an int[] constant?

There's no int[] constant. numbers is decayed to a pointer and numbers+1 is simple pointer arithmetic applied to the parameter passed to the recursive call.

于 2016-03-28T15:12:28.930 回答
11

作为@πάντα ῥεῖ 回答的旁注,以下是对术语的一些说明:

以下是描述数组表示法的另一种方式:

该短语numbers[1]也可以表示为*(numbers + 1) where *operator is said to dereference the pointer address numbers + 1在这种情况下,可以将取消引用视为读取 指向的值

因此,您示例中的代码使用指针算法。该短语numbers + 1是指针表示法,指向指针的第二个 int 位置numberssize - 1是从内存位置开始numbers到数组末尾的字节数。

至于衰减的含义:
通常,在C 数组参数的上下文中,衰减传达了数组参数经历类型和维度信息丢失的想法。const int numbers[]据说您(可以说)衰减int *,因此不再能够提供数组大小信息。(sizeof()例如,使用宏不提供数组的长度,而是指针的大小。)这也是提供第二个参数的原因,以传达大小信息。

但是,在这个问题的上下文中,衰减的含义是学术性的,正如@Ben Voigt 指出的那样:令牌序列 const int numbers[] 出现在形式参数列表中时,声明的是指针而不是数组。(它从未衰减为指针,因为它是一个开始的指针。)

于 2016-03-28T15:25:13.263 回答
4

正如πάντα ῥεῖ 所说, int[]衰减到int*.

但是这个sum功能是穷人的解决方案,你应该更喜欢accumulate

cout << accumulate(numbers, next(numbers, size), decay_t<decltype(numbers[0])>{});

Live Example

如果您有 C++17 和静态分配的数组,例如int numbers[size],您可以利用cbeginand cend

cout << accumulate(cbegin(numbers), cend(numbers), decay_t<decltype(numbers[0])>{});

我试图对递归进行基准测试sumaccumulate但是sum在我能够达到vector具有有意义差异的大小之前耗尽了堆栈空间,从而accumulate成为明显的赢家。


我将accumulate' initagument 的类型与numbers' 元素的类型相关联:decay_t<decltype(numbers[0])>{}。这样做的原因是,如果有人回来更改 的类型numbers,而不更改 的参数类型,accumulateinit累积将分配给错误的类型。

例如,如果我们使用累积线:cout << accumulate(cbegin(numbers), cend(numbers), 0),这对int numbers[]. 如果我们切换到 define: 就会出现问题,double numbers[] = {1.3, 2.3, 3.3, 4.3};但是我们没有改变init我们将 sum doubles 变成 an的参数int。这将导致 10 而不是 11.2:http: //ideone.com/A12xin

于 2016-03-28T15:25:56.130 回答
2
int sum(int *num,int size)
{
int total=0;
                                   /* function to sum integer array */
if (size <= 0) return(ERROR);
while(size--) total+= *num++;
return total;
}

更快、更紧凑、更容错。

于 2016-03-29T01:53:18.287 回答
1

numbers 是一个指针;在每次迭代中,函数 sum() 在数组中前进(这就是numbers+1所做的),同时将 size 减小 1(--size也可以)。

当 size 达到 0 时,这是退出条件,递归结束。

于 2016-03-29T01:43:42.470 回答