Обмен чисел с использованием указателей

CBeginner
Практиковаться сейчас

Введение

В программировании на языке C указатели (pointers) являются мощной возможностью, которая позволяет нам манипулировать данными, напрямую обращаясь к ячейкам памяти и изменяя их содержимое. Одна из распространенных применений указателей - это обмен значениями между двумя переменными без использования третьей переменной.

В этом лабораторном занятии (LabEx) мы научимся создавать программу на языке C, которая меняет местами два числа с использованием указателей. Этот метод является фундаментальным в различных сценариях программирования и демонстрирует практическое применение указателей для манипуляции памятью.

В рамках лабораторной работы вы научитесь создавать программу с нуля, компилировать ее и запускать, чтобы увидеть, как происходит обмен значениями.

Понимание указателей в языке C

Перед тем, как приступить к написанию кода, давайте разберемся, что такое указатели (pointers) и как они работают в языке C.

Что такое указатель?

Указатель - это переменная, которая хранит адрес памяти другой переменной. Указатели являются важной частью языка C, так как они позволяют напрямую обращаться к памяти и обеспечивают более эффективную манипуляцию данными.

Синтаксис указателей

В языке C указатели объявляются с использованием символа звездочки (*):

int *ptr;    // Declares a pointer to an integer

При работе с указателями мы используем два важных оператора:

  • Оператор взятия адреса (&) - возвращает адрес памяти переменной
  • Оператор разыменования (*) - позволяет получить значение, хранящееся по адресу, который содержится в указателе

Создание первого файла

Начнем с создания основного файла на языке C в директории проекта. Откройте среду разработки (IDE) и создайте новый файл с именем main.c:

  1. В панели проводника файлов (слева) перейдите в директорию /home/labex/project
  2. Щелкните правой кнопкой мыши и выберите "Новый файл"
  3. Назовите файл main.c
  4. Добавьте в файл следующую базовую структуру:
#include <stdio.h>

int main() {
    // We will add our code here

    return 0;
}

Это создаст простую программу на языке C с подключенной стандартной библиотекой ввода-вывода и главной функцией, которая возвращает 0 при успешном завершении программы.

Создание структуры программы для обмена значений

Теперь, когда мы понимаем, как работают указатели, давайте построим программу для обмена значений пошагово.

Объявление переменных и указателей

Нам нужно объявить:

  1. Две целочисленные переменные (a и b), в которых будут храниться значения, которые мы хотим поменять местами.
  2. Два целочисленных указателя (ptra и ptrb), которые будут хранить адреса переменных a и b.
  3. Временную переменную (temp), которая поможет в операции обмена значений.

Обновите файл main.c следующим кодом:

#include <stdio.h>

int main() {
    // Declare variables
    int a, b;
    int *ptra, *ptrb;
    int temp;

    // Get input from user
    printf("Enter value for a: ");
    scanf("%d", &a);

    printf("Enter value for b: ");
    scanf("%d", &b);

    // Display original values
    printf("\nOriginal values:\n");
    printf("a = %d\n", a);
    printf("b = %d\n", b);

    // We will add more code here in the next step

    return 0;
}

Понимание кода

Давайте проанализируем, что мы сделали до сих пор:

  1. Мы объявили две целочисленные переменные a и b, в которых будут храниться значения, которые мы хотим поменять местами.
  2. Мы объявили два целочисленных указателя ptra и ptrb, которые будут хранить адреса памяти переменных a и b.
  3. Мы объявили временную целочисленную переменную temp, которая поможет нам в операции обмена значений.
  4. Мы добавили код, чтобы запросить у пользователя значения для переменных a и b.
  5. Мы добавили код, чтобы отобразить исходные значения переменных a и b.

Обратите внимание, что в функции scanf мы используем оператор взятия адреса (&), чтобы сообщить функции, где в памяти хранить введенные значения.

Реализация логики обмена значений

Теперь давайте реализуем фактическую логику обмена значений с использованием указателей.

Присваивание адресов указателям

Сначала нам нужно сделать так, чтобы наши указатели указывали на наши переменные, присвоив адреса переменных a и b соответственно указателям ptra и ptrb:

// Assign addresses to pointers
ptra = &a;
ptrb = &b;

Алгоритм обмена значений с использованием указателей

Ключ к обмену значений с помощью указателей - это манипулирование значениями в ячейках памяти, а не просто указателями самими по себе. Вот как мы это сделаем:

  1. Сохраните значение переменной a (доступное через *ptra) во временной переменной temp.
  2. Присвойте значение переменной b (доступное через *ptrb) переменной a (с использованием *ptra).
  3. Присвойте временное значение (исходное значение переменной a) переменной b (с использованием *ptrb).

Обновите файл main.c, добавив следующий код в место, указанное на предыдущем шаге:

#include <stdio.h>

int main() {
    // Declare variables
    int a, b;
    int *ptra, *ptrb;
    int temp;

    // Get input from user
    printf("Enter value for a: ");
    scanf("%d", &a);

    printf("Enter value for b: ");
    scanf("%d", &b);

    // Display original values
    printf("\nOriginal values:\n");
    printf("a = %d\n", a);
    printf("b = %d\n", b);

    // Assign addresses to pointers
    ptra = &a;
    ptrb = &b;

    // Display memory addresses (optional but helpful for understanding)
    printf("\nMemory addresses:\n");
    printf("Address of a: %p\n", ptra);
    printf("Address of b: %p\n", ptrb);

    // Swap the values using pointers
    temp = *ptra;    // Store value of a in temp
    *ptra = *ptrb;   // Assign value of b to a
    *ptrb = temp;    // Assign original value of a to b

    // Display swapped values
    printf("\nAfter swapping:\n");
    printf("a = %d\n", a);
    printf("b = %d\n", b);

    return 0;
}

Понимание логики обмена значений

Давайте разберёмся, как именно работает обмен значений:

  1. temp = *ptra; - Оператор * разыменовывает указатель, давая доступ к значению в ячейке памяти. Эта строка сохраняет значение переменной a в переменной temp.
  2. *ptra = *ptrb; - Эта строка присваивает значение переменной b ячейке памяти переменной a, фактически изменяя значение переменной a.
  3. *ptrb = temp; - Эта строка присваивает исходное значение переменной a (сохраненное в temp) ячейке памяти переменной b, завершая обмен значений.

После этих операций переменные a и b поменяли значения без прямого изменения их - мы только изменили значения в их ячейках памяти.

Компиляция и тестирование программы для обмена значений

Теперь, когда мы завершили написание программы, давайте скомпилируем и запустим ее, чтобы увидеть результаты.

Компиляция программы

Для компиляции программы мы будем использовать GNU C Compiler (gcc). Откройте терминал в WebIDE и выполните следующую команду:

cd ~/project
gcc main.c -o swap_program

Эта команда компилирует наш файл main.c и создает исполняемый файл с именем swap_program.

Запуск программы

Теперь давайте запустим нашу программу, чтобы проверить, правильно ли она меняет местами значения:

./swap_program

Вам будет предложено ввести значения для переменных a и b. Например, введем:

  • a = 5
  • b = 10

Программа должна отобразить:

  • Исходные значения: a = 5, b = 10
  • Адреса памяти переменных a и b
  • Поменянные местами значения: a = 10, b = 5

Понимание вывода программы

При запуске программы вы увидите несколько разделов вывода:

  1. Исходные значения - показывает значения до обмена.
  2. Адреса памяти - показывает, где в памяти хранятся переменные (каждый раз при запуске программы они будут разными).
  3. После обмена - показывает значения после операции обмена.

Попробуйте запустить программу несколько раз с разными входными значениями, чтобы убедиться, что обмен работает стабильно.

Как это работает "под капотом"?

Давайте визуализируем, что происходит в памяти:

  1. Изначально, если a = 5 и b = 10, каждая из них имеет свою собственную ячейку памяти.
  2. ptra указывает на ячейку памяти переменной a.
  3. ptrb указывает на ячейку памяти переменной b.
  4. Во время обмена:
    • temp получает значение по адресу ptra (которое равно 5).
    • Значение по адресу ptra меняется на значение по адресу ptrb (которое равно 10).
    • Значение по адресу ptrb меняется на значение temp (которое равно 5).
  5. После обмена a = 10 и b = 5, фактически поменяв местами свои значения.

Это демонстрирует мощь указателей - они позволяют нам косвенно изменять значения, напрямую манипулируя ячейками памяти.

Резюме

В этом практическом занятии (лабораторной работе) мы научились использовать указатели в языке C для обмена значений двух переменных. Основные концепции, которые были рассмотрены:

  1. Указатели: Переменные, которые хранят адреса памяти других переменных.
  2. Адреса памяти: Уникальные места в компьютерной памяти, где хранятся данные.
  3. Операции с указателями:
    • Оператор взятия адреса (&) для получения адреса памяти переменной.
    • Оператор разыменования (*) для доступа к значению по адресу памяти.
  4. Алгоритм обмена: Использование временной переменной и указателей для обмена значений.

Эта техника является фундаментальной концепцией в программировании на языке C и демонстрирует мощь указателей для манипуляции памятью. Она может быть применена в различных сценариях программирования, таких как алгоритмы сортировки, операции с структурами данных и реализация функций.

Понимая, как манипулировать данными через адреса памяти, вы сделали важный шаг в овладении программированием на языке C и концепциями компьютерной памяти.