Указатели и массивы
В C указатели и массивы — близкие друзья. Имя массива, использованное само по себе, — это адрес его первого элемента. Поэтому его можно сохранить в указателе без &:
#include <stdio.h>
int main(void) {
int numbers[] = {3, 7, 1};
int *p = numbers;
printf("%d\n", *p);
printf("%d\n", p[1]);
return 0;
}Программа выведет:
3
7int *p = numbers; означает то же, что и int *p = &numbers[0];, поэтому *p — первый элемент. А с указателем можно пользоваться квадратными скобками так же, как с массивом: p[1] — это элемент сразу после того, на который указывает p, здесь 7.
Элементы массива лежат в памяти вплотную друг к другу. p + 1 — адрес следующего элемента, а p[1] — более короткая запись *(p + 1). В этом курсе используются квадратные скобки, но другую форму вы увидите в других программах на C.
Вспомните ошибку из урока «Массивы»: вывод целого массива через printf("%d\n", scores); не компилируется, а в сообщении сказано the argument has type 'int *'. Теперь понятно почему: имя массива — это адрес типа int *, а не число для %d.
Это объясняет и кое-что из урока «Функции». Когда вы передаёте массив в функцию, C его не копирует. Он передаёт только адрес его первого элемента. Параметр int numbers[] на самом деле указатель, поэтому его можно записать и как int *numbers. Оба варианта означают абсолютно одно и то же:
#include <stdio.h>
void double_all(int *numbers, int count) {
for (int i = 0; i < count; i++) {
numbers[i] *= 2;
}
}
int main(void) {
int prices[] = {10, 25, 40};
double_all(prices, 3);
printf("%d %d %d\n", prices[0], prices[1], prices[2]);
return 0;
}Программа выведет:
20 50 80Через адрес функция работает с массивом вызывающей стороны, поэтому её изменения сохраняются. Поэтому же функции нужно количество элементов: она получает только адрес первого элемента и не может узнать, где массив заканчивается. Даже sizeof(numbers) / sizeof(numbers[0]) внутри функции не поможет. Там numbers — указатель, поэтому sizeof даёт размер указателя, и результат неверный (здесь он равен 1). Только там, где массив был создан, как в main, sizeof видит весь массив. Поэтому всегда передавайте количество элементов отдельным параметром.
Задание
- 1
В конце
main(передreturn 0;) создайте указательpна первый элементscores:int *p = scores;. - 2
Ниже выведите два элемента через указатель: текст
Первый:и*p, а на следующей строкеВторой:иp[1]. Программа выведетПервый: 12иВторой: 7. - 3
Измените параметр
print_allсint numbers[]наint *numbers. Программа выведет то же, что и раньше, потому что оба варианта означают одно и то же. - 4
Ниже
print_allнапишите функциюadd_to_allс параметрамиint *numbers,int countиint amount, которая прибавляетamountк каждому элементу. В концеmainвызовите её сscores,4и5, а затем ещё раз вызовитеprint_all(scores, 4). Последняя строка вывода:17 12 20 14.