C++ Арифметика указателей
Указатель — это адрес, представленный числовым значением. Поэтому с указателями можно выполнять арифметические операции. Над указателями можно выполнять четыре арифметические операции: ++, --, +, -.
Предположим,ptr— это целочисленный указатель, указывающий на адрес 1000, 32-битное целое число. Выполним над этим указателем следующие арифметические операции:
ptr++
После выполнения ptr++ указатель ptr переместится вперёд на 4 байта и будет указывать на адрес следующего целочисленного элемента. Это объясняется тем, что арифметика указателей определяет величину смещения на основе типа и размера указателя. В данном случае, поскольку это 32-битный целочисленный указатель, каждое целое число занимает 4 байта, поэтому ptr++ переместит указатель ptr вперёд на 4 байта, и он будет указывать на адрес следующего целочисленного элемента.
еслиptrуказывает на символ по адресу 1000. Когда выполняется ptr++, значение указателя ptr увеличится и будет указывать на адрес следующего символьного элемента. Поскольку ptr — это указатель на символ, а каждый символ занимает 1 байт, ptr++ увеличит значение ptr на 1, и после выполнения ptr указывает на адрес 1001.
Подробный анализ операций арифметики указателей:
Операция сложения: с указателями можно выполнять сложение. Когда к указателю p прибавляется целое число n, указатель p смещается вперёд на размер n элементов. Например, если p — указатель на int и каждый int занимает 4 байта, то p + 1 будет указывать на следующий элемент int после того, на который указывает p.
Операция вычитания: с указателями можно выполнять вычитание. Когда из указателя p вычитается целое число n, указатель p смещается назад на размер n элементов. Например, если p — указатель на int и каждый int занимает 4 байта, то p - 1 будет указывать на предыдущий элемент int перед тем, на который указывает p.
Вычитание указателей: можно вычислить расстояние между двумя указателями. Когда из одного указателя q вычитается другой указатель p, результатом является количество элементов между двумя указателями. Например, если p и q — оба указатели на int и каждый int занимает 4 байта, то p - q даст количество элементов между двумя указателями.
Операция сравнения между указателем и целым числом: можно сравнивать указатель с целым числом. Можно использовать операторы отношения (такие как <, >, <=, >=) для сравнения указателей с целыми числами. Это сравнение обычно используется для определения, указывает ли указатель на допустимую область памяти.
Инкремент указателя
В C++ указатель — это переменная, которая хранит адрес памяти. Инкрементирование указателя означает, что указатель начинает указывать на следующую область памяти, что обычно означает указание на следующий элемент массива. Инкрементирование указателя автоматически изменяет значение указателя в соответствии с типом данных, на который указывает указатель.
Например, если указатель указывает на элемент массива int, то инкрементирование указателя заставит его указывать на следующий элемент int. Вот простой пример, демонстрирующий, как инкрементировать указатель:
Пример
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
指针当前指向的元素: 10 递增指针后指向的元素: 20
В этом примере указательptrИзначально указывает на массивarrпервый элемент. Выполнивptr++, указательptrинкрементируется, чтобы указывать на следующий элемент массива (то есть на второй элемент).
При инкрементировании указателя значение указателя увеличится на смещение, равное размеру типа данных, на который указывает указатель. Например, если указатель имеет типint*тип, каждое инкрементирование указателя будет увеличивать его на 4 байта (при условииintтип занимает 4 байта).
Следует отметить, что при использовании операций с указателями необходимо убедиться, что указатель указывает на допустимую область памяти; в противном случае это может привести к неопределенному поведению или сбоям программы. При работе с массивами будьте особенно внимательны, чтобы избежать выхода указателей за границы массива.
Декрементирование указателя
В C++ указатели можно не только инкрементировать, но и декрементировать. Декрементирование указателя означает, что указатель начинает указывать на предыдущую ячейку памяти. Подобно инкрементированию указателя, декрементирование указателя также автоматически корректирует значение указателя в соответствии с типом данных, на который указывает указатель.
Вот простой пример, демонстрирующий, как уменьшить указатель:
Пример
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
指针当前指向的元素: 20 递减指针后指向的元素: 10
В этом примере указательptrИзначально указывает на массивarrвторой элемент. При выполненииptr--, указательptrуменьшается так, что начинает указывать на первый элемент массива.
При декременте указателя значение указателя уменьшается на смещение, равное размеру типа данных, на который указывает указатель. Например, если указатель имеет типint*типа, каждый декремент указателя будет уменьшать его на 4 байта (при условииintтип занимает 4 байта).
Сравнение указателей
В C++ операции сравнения указателей можно использовать для определения, указывают ли два указателя на одно и то же место, указывает ли один указатель на место до или после местоположения другого указателя, и т. д. Сравнение указателей в основном включает следующее:
- Сравнение на равенство (
==и!=) - Сравнение отношений (
<,<=,>,>=)
Сравнение на равенство
Сравнение на равенство используется для проверки, указывают ли два указателя на одно и то же место.
Пример
int main() {
int a = 10;
int b = 20;
int* ptr1 = &a;
int* ptr2 = &a;
int* ptr3 = &b;
// Сравнить, равны ли указатели
if (ptr1 == ptr2) {
std::cout << ptr1 и ptr2 указывают на одно и то же место << std::endl;
} else {
std::cout << ptr1 и ptr2 указывают на разные места << std::endl;
}
if (ptr1 != ptr3) {
std::cout << ptr1 и ptr3 указывают на разные места << std::endl;
} else {
std::cout << ptr1 и ptr3 указывают на одно и то же место << std::endl;
}
return 0;
}
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
ptr1 和 ptr2 指向相同的位置 ptr1 和 ptr3 指向不同的位置
Сравнение отношений
Реляционное сравнение используется для определения того, указывает ли один указатель на местоположение перед или после местоположения другого указателя. Обычно это имеет смысл, когда указатели указывают на элементы одного и того же массива.
Пример
int main() {
int arr[] = {10, 20, 30, 40, 50};
int* ptr1 = &arr[1]; // Указывает на второй элемент массива
int* ptr2 = &arr[3]; // Указывает на четвёртый элемент массива
// Сравнение относительных позиций указателей
if (ptr1 < ptr2) {
std::cout << Элемент, на который указывает ptr1, находится перед элементом, на который указывает ptr2 << std::endl;
} else {
std::cout << Элемент, на который указывает ptr1, не находится перед элементом, на который указывает ptr2 << std::endl;
}
if (ptr2 > ptr1) {
std::cout << Элемент, на который указывает ptr2, находится после элемента, на который указывает ptr1 << std::endl;
} else {
std::cout << Элемент, на который указывает ptr2, не находится после элемента, на который указывает ptr1 << std::endl;
}
return 0;
}
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
ptr1 指向的元素在 ptr2 指向的元素之前 ptr2 指向的元素在 ptr1 指向的元素之后
Полный пример сравнения указателей:
Пример
int main() {
int arr[] = {10, 20, 30, 40, 50};
int* ptr1 = &arr[1]; // Указывает на второй элемент массива
int* ptr2 = &arr[3]; // Указывает на четвёртый элемент массива
int* ptr3 = &arr[1]; // Указывает на второй элемент массива
// Сравнение на равенство
if (ptr1 == ptr3) {
std::cout << ptr1 и ptr3 указывают на одно и то же место << std::endl;
} else {
std::cout << ptr1 и ptr3 указывают на разные места << std::endl;
}
if (ptr1 != ptr2) {
std::cout << ptr1 и ptr2 указывают на разные места << std::endl;
} else {
std::cout << ptr1 и ptr2 указывают на одно и то же место << std::endl;
}
// Реляционное сравнение
if (ptr1 < ptr2) {
std::cout << Элемент, на который указывает ptr1, находится перед элементом, на который указывает ptr2 << std::endl;
} else {
std::cout << Элемент, на который указывает ptr1, не находится перед элементом, на который указывает ptr2 << std::endl;
}
if (ptr2 > ptr1) {
std::cout << Элемент, на который указывает ptr2, находится после элемента, на который указывает ptr1 << std::endl;
} else {
std::cout << Элемент, на который указывает ptr2, не находится после элемента, на который указывает ptr1 << std::endl;
}
return 0;
}
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
ptr1 和 ptr3 指向相同的位置 ptr1 和 ptr2 指向不同的位置 ptr1 指向的元素在 ptr2 指向的元素之前 ptr2 指向的元素在 ptr1 指向的元素之后
Примечания
Сравнения в пределах одного массива: Реляционные сравнения (такие как
<,>,<=,>=) между элементами одного и того же массива имеют смысл. Если указатели не принадлежат одному массиву, результат реляционного сравнения не определён.Указатель является нулевым: Перед сравнением указателей убедитесь, что указатели не являются нулевыми указателями (
nullptr), иначе это может вызвать неопределённое поведение.