Pointers: &, *, and pass-by-pointer · Указатели: &, *, и передача по указателю
A problem from last lesson
- Last lesson, a function got a copy of your number. Changing the copy did not change the original.
- C copies every argument you pass to a function. So a normal function cannot change your variable.
- To change it, the function needs the variable's address — where it lives in memory.
Задача из прошлого урока
- В прошлом уроке функция получила копию вашего числа. Изменение копии не изменило оригинал.
- C копирует каждый аргумент, который вы передаете функции. Поэтому обычная функция не может изменить вашу переменную.
- Чтобы изменить её, функция должна получить адрес переменной — где она находится в памяти.
Every variable has an address
- Think of a variable as a box in memory. The value is kept inside the box.
- Every box has an address: a number that says where the box is.
- The
&operator gives you that address.&xmeans "the address ofx".
У каждой переменной есть адрес
- Представьте переменную как коробку в памяти. Значение хранится внутри коробки.
- У каждой коробки есть адрес: число, указывающее, где находится коробка.
- Оператор
&дает вам этот адрес. ⟨&x⟩ означает "адрес ⟨x⟩".
A pointer holds an address
- A pointer is a variable that stores an address, not a normal value.
- You declare one with a
*:int *p = &x;reads as "ppoints tox". - To reach the value at that address, put
*in front:*p. This is called dereference. - Changing
*pchanges the original variable.*p = 5;puts5intoxitself.
Указатель хранит адрес
- Указатель — это переменная, хранящая адрес, а не обычное значение.
- Вы объявляете его с помощью ⟨
*⟩: ⟨int *p = &x;⟩ читается как «pуказывает на ⟨x⟩». - Чтобы получить значение по этому адресу, поставьте ⟨
*⟩ в начало: ⟨*p⟩. Это называется разыменованием. - Изменение ⟨
*p⟩ изменяет исходную переменную. ⟨*p = 5;⟩ помещает ⟨5⟩ непосредственно в ⟨x⟩.
#include <stdio.h>
void set_to_five(int *p) {
*p = 5; // change the value at the address
}
int main(void) {
int x = 0;
set_to_five(&x); // pass the ADDRESS of x
printf("%d\n", x); // 5 — the original changed!
return 0;
}
Out-pointers: giving back more than one answer
- A function can
returnonly one value. But it can change several variables through pointers. - You pass the address of each answer, like
find(&min, &max). The function writes into them with*. - These extra pointer parameters are called out-pointers. The caller reads the answers after the call.
- A pointer that points to nothing is
NULL. Never dereference aNULLpointer.
Out-pointers: возврат нескольких значений
- Функция может
returnтолько одно значение. Но она может изменить несколько переменных через указатели. - Вы передаёте адрес каждого ответа, как
find(&min, &max). Функция записывает в них с помощью*. - Эти дополнительные параметры-указатели называются out-pointers. Вызывающий код считывает результаты после вызова.
- Указатель, который никуда не указывает, равен
NULL. Никогда не разыменовывайте указательNULL.
Common mistakes
&xis the address ofx;*pis the value stored atp.- Never use
*pon an uninitialised orNULLpointer.
Распространенные ошибки
&x— это адресx;*p— значение, хранящееся по адресуp.- Никогда не используйте
*pна неинициализированном илиNULLуказателе.
Now you try
- Each task gives you a function to complete. Use
*to read or change the value the pointer points to. - When a value comes in through a pointer (like
int *p), write your answer through it — do notreturnit. - Do not write a
main— the checker provides one. Press Run, then Check answer.
Теперь попробуйте сами
- Каждое задание содержит функцию, которую нужно завершить. Используйте
*для чтения или изменения значения, на которое указывает указатель. - Когда значение поступает через указатель (как
int *p), запишите свой ответ через него — неreturnего. - Не пишите
main— контрольная программа предоставит его. Нажмите Run (Запустить), затем Check answer (Проверить ответ).
Complete void add_one(int *p) so it adds 1 to the int that p points at. Use *p. Do not write a main — the checker provides one. · Завершите void add_one(int *p) так, чтобы она прибавляла 1 к int, на который указывает p. Используйте *p. Не пишите main — чекер предоставляет его сам.
Click Run to see the output here. · Нажмите Запустить, чтобы увидеть результат здесь.
Complete void swap(int *a, int *b) so it exchanges the two ints. Use a temporary variable. Do not write a main. · Завершите void swap(int *a, int *b) так, чтобы она меняла местами два int. Используйте временную переменную. Не пишите main.
Click Run to see the output here. · Нажмите Запустить, чтобы увидеть результат здесь.
Complete void min_max(const int a[], int n, int *min_out, int *max_out). Scan the array, then write the smallest value through min_out and the largest through max_out. Assume n >= 1. Do not write a main. · Завершите void min_max(const int a[], int n, int *min_out, int *max_out). Отсканируйте массив, затем запишите наименьшее значение через min_out и наибольшее через max_out. Предположите, что n >= 1. Не пишите main.
Click Run to see the output here. · Нажмите Запустить, чтобы увидеть результат здесь.