Классический пример: Swap
Часть раздела Logic & Flow путешествия по C на Coddy — урок 28 из 63.
Функция swap — один из самых известных примеров, демонстрирующих, почему указатели необходимы в программировании на C. Цель проста: написать функцию, которая меняет местами значения двух переменных. Однако эта, казалось бы, простая задача выявляет фундаментальное ограничение передачи по значению (pass-by-value).
Рассмотрим, что произойдет, если вы попытаетесь поменять значения двух переменных, используя обычную передачу по значению:
void badSwap(int a, int b) {
int temp = a;
a = b;
b = temp;
// Это меняет местами только копии, а не исходные переменные!
}Этот подход не работает, так как функция получает только копии значений. Оригинальные переменные в вызывающей функции остаются неизменными.
Решение требует передачи указателей на переменные вместо самих переменных:
void swap(int *a, int *b) {
int temp = *a; // Сохраняем значение по адресу a
*a = *b; // Помещаем значение из адреса b в адрес a
*b = temp; // Помещаем сохраненное значение в адрес b
}Передавая адреса переменных и используя оператор разыменования, функция может напрямую изменять значения исходных переменных. Это делает функцию swap идеальной демонстрацией того, когда и почему вам нужны указатели для выполнения задач, с которыми простая передача по значению (pass-by-value) просто не может справиться.
Задание
ЛегкоНапишите программу на языке C, которая реализует и демонстрирует классическую функцию перестановки (swap) с использованием указателей. Ваша программа должна:
- Создать функцию с именем
swap, которая принимает два указателя на целые числа в качестве параметров - Внутри функции
swapобменять значения по адресам памяти, на которые указывают эти два указателя, используя временную переменную - В функции
mainсчитать два целых числа из пользовательского ввода - Вывести исходные значения в формате:
Before swap: a = [value], b = [value] - Вызвать функцию
swapи передать адреса обеих переменных, используя оператор взятия адреса - После вызова функции вывести измененные значения в формате:
After swap: a = [value], b = [value]
Ваш вывод должен демонстрировать, что функция успешно обменивает значения исходных переменных:
Before swap: a = [first_input], b = [second_input]
After swap: a = [second_input], b = [first_input]Эта задача демонстрирует, почему указатели необходимы для операции перестановки — функция должна иметь доступ к ячейкам памяти исходных переменных, чтобы навсегда изменить их значения, что невозможно при передаче по значению.
Шпаргалка
Функция swap демонстрирует, почему указатели важны в C. Передача по значению не может поменять местами исходные переменные, так как функции получают только копии:
void badSwap(int a, int b) {
int temp = a;
a = b;
b = temp;
// Это меняет местами только копии, а не исходные переменные!
}Правильный подход использует указатели для доступа и изменения исходных переменных:
void swap(int *a, int *b) {
int temp = *a; // Сохраняем значение по адресу a
*a = *b; // Помещаем значение из адреса b в адрес a
*b = temp; // Помещаем сохраненное значение в адрес b
}Передавая адреса и используя оператор разыменования (*), функция может напрямую изменять значения исходных переменных.
Попробуйте сами
#include <stdio.h>
// TODO: Напишите вашу функцию swap здесь
int main() {
int a, b;
// Чтение входных данных
scanf("%d", &a);
scanf("%d", &b);
// Вывод исходных значений
printf("Before swap: a = %d, b = %d\n", a, b);
// TODO: Вызовите вашу функцию swap здесь
// Вывод значений после обмена
printf("After swap: a = %d, b = %d\n", a, b);
return 0;
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Logic & Flow
1Основы указателей
Что такое указатель?Объявление указателейОператор взятия адреса (&)Оператор разыменования (*)Указатели NULLИтоги: Основы указателей4Проект: Простая текстовая утилита
Обзор проектаПодсчет символов2Указатели и массивы
Имена массивов как указателиЭлементы массива — указателиАрифметика указателейСравнение указателейИтоги: Обход массива через указатели5Указатели и функции
Передача по значениюПередача указателей в функцииИзменение переменных через указателиКлассический пример: SwapПередача массивов в функцииИтоги: указатели как аргументы функций8Структуры и указатели
Указатели на структурыОператор «стрелка» (->)Передача структур по значениюПередача указателей на структурыДинамическое выделение памяти для структурИтоги: Изменение структур через указатели11Итоговые задачи на повторение
Повторение: динамическая конкатенация строкПовторение: массив структурПовторение: счетчик частоты слов3Символьные массивы и строки
Строки как массивы charНуль-терминаторВвод строк с помощью scanfИспользование strlen()Использование strcpy()Использование strcat()Использование strcmp()Итоги: основные строковые функции