Добавление целых чисел к массивам в C ++?

Рассматривать:

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[] постоянная?

15

Решение

как работает «число + 1», если число [] является массивом int, и вы не можете добавить целое число к константе int []?

Нет никаких int[] постоянная. numbers распадается на указатель и numbers+1 простая арифметика указателей, применяемая к параметру, передаваемому рекурсивному вызову.

19

Другие решения

В качестве дополнительного примечания к ответу @ πάντα ῥεῖ приведем несколько пояснений по терминологии:

Ниже приведен еще один способ отображения обозначения массива:

Фраза numbers[1] также может быть выражено как *(numbers + 1)
Где * оператор сказал разыменовать адрес указателя numbers + 1,
разыменовать в этом случае можно думать как прочитайте значение, на которое указывает.

Итак, код в вашем примере использует арифметика указателей. Фраза numbers + 1 это обозначение указателя, указывающее на второе int расположение указателя numbers, size - 1 это количество байтов из ячейки памяти, начиная с numbers до конца массива.

Что касается значения гнилой:
Как правило, в контексте Аргументы массива C, распад передает идею, что аргумент массива испытывает потерю информации о типе и измерении. Ваш const int numbers[] сказано (возможно) распад в int *поэтому больше не может предоставить информацию о размере массива. (С использованием sizeof() макрос, например, не предоставляет длину массива, но размер указателя.) Это также является причиной, по которой предоставляется второй аргумент для передачи информации о размере.

тем не мение, в контексте этого вопроса значение распад является академическим, как отмечает @Ben Voigt: Последовательность токенов const int numbers [], когда она появляется в списке формальных параметров, объявляет указатель, а не массив. (Он никогда не превращался в указатель, потому что это был указатель для начала.)

10

Как πάντα ῥεῖ говорит int[] распадается на int*,

Но это sum функция — это решение для бедняка, вы должны предпочесть accumulate:

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

Живой пример

Если у вас есть C ++ 17 и статически распределенный массив, такой как int numbers[size], вы можете воспользоваться cbegin а также cend:

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

Я попытался сравнить рекурсивный sum против accumulate, тем не мение sum не хватает места в стеке, прежде чем я смогу достичь vector размер со значительной разницей, делая accumulate явный победитель.


Я ассоциирую тип accumulate«s init агмент с типом numbers‘элементы: decay_t<decltype(numbers[0])>{}, Причина этого в том, если кто-то должен был вернуться и изменить тип numbers, а не менять тип accumulate«s init В качестве аргумента накопление будет присвоено неправильному типу.

Например, если мы используем строку накопления: cout << accumulate(cbegin(numbers), cend(numbers), 0)это хорошо для int numbers[], Проблема возникнет, если мы перейдем к определению: double numbers[] = {1.3, 2.3, 3.3, 4.3}; но мы не смогли изменить init аргумент, который мы суммируем doubleв int, Это приведет к 10, а не 11,2: http://ideone.com/A12xin

4

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;
}

Быстрее, компактнее и устойчивее к ошибкам.

2

число указатель; на каждой итерации функция sum () перемещается по массиву (вот что номера + 1 делает), одновременно уменьшая размер на 1 (—размер будет работать так же хорошо).

Когда размер достигает 0, это условие выхода, и рекурсия заканчивается.

1