Арифметика указателей
Часть раздела Logic & Flow путешествия по C на Coddy — урок 9 из 63.
Вы узнали, как обращаться к элементам массива, используя указательную нотацию, такую как *(array + i). Теперь вы познакомитесь с еще более мощным методом: арифметика указателей, которая позволяет перемещать указатели по памяти с помощью простых операций инкремента и декремента.
Когда вы увеличиваете указатель с помощью ++ или уменьшаете его с помощью --, указатель не просто перемещается на один байт. Вместо этого он перемещается на размер типа данных, на который он указывает. Для целочисленного указателя ptr++ перемещается вперед на sizeof(int) байт, попадая точно на следующее целое число в памяти.
int numbers[5] = {10, 20, 30, 40, 50};
int *ptr = numbers; // Указывает на первый элемент (10)
ptr++; // Теперь указывает на второй элемент (20)
ptr++; // Теперь указывает на третий элемент (30)Этот автоматический расчет размера делает арифметику указателей такой мощной и удобной. Вам не нужно беспокоиться о вычислениях байтов — C берет на себя адресацию памяти за вас на основе типа данных указателя.
Арифметика указателей особенно полезна для обхода массивов в циклах. Вместо использования индексов массива вы можете инкрементировать указатель, чтобы последовательно перемещаться по каждому элементу, что часто приводит к более эффективному коду.
Задание
ЛегкоНапишите программу на языке C, которая демонстрирует арифметику указателей, используя операции инкремента указателя для обхода и обработки массива. Ваша программа должна:
- Объявить целочисленный массив с именем
dataиз 5 элементов и инициализировать его значениями {12, 24, 36, 48, 60} - Объявить указатель на целое число с именем
ptrи инициализировать его так, чтобы он указывал на первый элемент массива - Использовать цикл for, который выполняется 5 раз, для обхода всего массива, используя только арифметику указателей
- Внутри цикла:
- Вывести текущее значение, на которое указывает
ptr, используя оператор разыменования - Вывести адрес памяти, хранящийся в
ptr, используя спецификатор формата%p - Увеличить указатель с помощью
ptr++, чтобы перейти к следующему элементу
- Вывести текущее значение, на которое указывает
- После цикла сбросить
ptr, чтобы он снова указывал на первый элемент массива - Использовать арифметику указателей для прямого доступа и вывода третьего элемента (индекс 2), используя
*(ptr + 2) - Использовать арифметику указателей для прямого доступа и вывода последнего элемента (индекс 4), используя
*(ptr + 4)
Ваш вывод должен отображать результаты в следующем формате:
Value: 12, Address: [address]
Value: 24, Address: [address]
Value: 36, Address: [address]
Value: 48, Address: [address]
Value: 60, Address: [address]
Third element: 36
Last element: 60Эта задача проверяет ваше понимание того, как операции инкремента указателя автоматически перемещаются на размер типа данных, и как вы можете использовать арифметику указателей для доступа к элементам массива по определенным смещениям от базовой позиции указателя.
Шпаргалка
Арифметика указателей позволяет перемещать указатели по памяти с помощью операций инкремента и декремента. Когда вы увеличиваете указатель, он перемещается на размер типа данных, на который он указывает, а не на один байт.
Основные операции арифметики указателей:
int numbers[5] = {10, 20, 30, 40, 50};
int *ptr = numbers; // Указывает на первый элемент (10)
ptr++; // Теперь указывает на второй элемент (20)
ptr++; // Теперь указывает на третий элемент (30)Вы также можете использовать арифметику указателей для доступа к элементам по определенным смещениям:
*(ptr + 2) // Доступ к элементу со смещением 2 от текущей позицииАрифметика указателей полезна для обхода массивов в циклах, что часто приводит к более эффективному коду, чем использование индексов массива.
Попробуйте сами
#include <stdio.h>
int main() {
// TODO: Напишите свой код здесь
// Объявите и инициализируйте массив 'data' значениями {12, 24, 36, 48, 60}
// Объявите указатель 'ptr' и инициализируйте его так, чтобы он указывал на первый элемент
// Используйте цикл for с арифметикой указателей для обхода массива
// Выведите каждое значение и адрес, затем увеличьте указатель
// Сбросьте указатель и используйте арифметику указателей для доступа к конкретным элементам
return 0;
}В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Logic & Flow
1Основы указателей
Что такое указатель?Объявление указателейОператор взятия адреса (&)Оператор разыменования (*)Указатели NULLИтоги: Основы указателей4Проект: Простая текстовая утилита
Обзор проектаПодсчет символов2Указатели и массивы
Имена массивов как указателиЭлементы массива — указателиАрифметика указателейСравнение указателейИтоги: Обход массива через указатели5Указатели и функции
Передача по значениюПередача указателей в функцииИзменение переменных через указателиКлассический пример: SwapПередача массивов в функцииИтоги: указатели как аргументы функций8Структуры и указатели
Указатели на структурыОператор «стрелка» (->)Передача структур по значениюПередача указателей на структурыДинамическое выделение памяти для структурИтоги: Изменение структур через указатели11Итоговые задачи на повторение
Повторение: динамическая конкатенация строкПовторение: массив структурПовторение: счетчик частоты слов3Символьные массивы и строки
Строки как массивы charНуль-терминаторВвод строк с помощью scanfИспользование strlen()Использование strcpy()Использование strcat()Использование strcmp()Итоги: основные строковые функции