16 сентября 2021
Упражнение 1. Написать программу для вывода первых n
чисел Фибоначчи.
Упражнение 2. Написать программу для проверки простоты натурального числа. Число вводится с клавиатуры.
Передача аргументов в функцию в Си
Передача агрумента в функию происходит по значению. Это значит, что в функцию передается копия переменной, которая имеет то же значение. Это значит, что передав аргумент типа int
в функцию, мы не сможем изменить ее значение:
#include <stdio.h>
void increment(int a) {
++a;
}
int main() {
int value = 2;
printf("%d ", value);
increment(value);
printf("%d\n", value);
return 0;
}
Эта программа увеличила значение переменной a
, которая существует только внутри функции increment
. Значение переменной value
в функции main
осталось неизменным:
2 2
Мы научимся изменять значение переменной в функции, рассмотрев указатели.
Указатели
Каждой переменной соответствует некоторое место в памяти со своим уникальным адресом. Оператор &
позволяет получить адрес в памяти, соответствующий переменной:
int a = 1;
int b = 2;
int c = 3;
printf("%x %d\n", &a, a);
printf("%x %d\n", &b, b);
printf("%x %d\n", &c, c);
В результате выполнения этого кода автор получилось:
61fecc 1
61fec8 2
61fec4 3
(адреса выведены в шеснадцатиричной системе счисления). Единица памяти соответствует одному байту. Видно, что переменные int
расположены в памяти с шагом 4
байта (32
бита), что соответствует размеру типа int
на компьютере автора.
Упражнение. Воспроизведите этот пример для других типов данных (например, double
). Какой интервал между адресами переменных получается в этих случаях?
В Си существуют специальные переменные, которые хранять адрес в памяти, их называют указателями. Объявить указатель можно так:
int a = 5;
int *ptr = &a;
Переменная ptr
хранит адрес переменной a
. Чтобы получить значение переменной через указатель необходимо использовать оператор разыменовывания *
:
int b = *ptr;
printf("%d %d %d\n", a, *ptr, b);
printf("%x %x %x\n", &a, ptr, &b);
Получим:
5 5 5
61fec8 61fec8 61fea4
Выражения &a
и ptr
соответствуют адресу 61fec8
, а выражение &b
- адресу 61fea4
.
Указатель можно использовать для измерения значения переменной:
int value = 6;
int *vptr = &value;
*vptr = 11;
printf("value = %d\n", value);
Получим:
value = 11
Если передать указатель на переменную в виде аргумента функции, то функция сможет изменить значение переменной:
void increment(int* a) {
++*a;
}
int value = 2;
printf("%d\n", value);
increment(&value);
printf("%d\n", value);
Получим:
2
3
Пример. Функция swap. Одна из часто используемых операций в программировании - обмен значений между двумя переменными. Используя указатели, мы можем написать функцию swap
:
void swap(int *a, int *b) {
int tmp = *b;
*b = *a;
*a = tmp;
}
Упражнение. Напишите версию функции swap
, которая не использует дополнительные переменных.