C Арифметика указателей
. Поскольку ptr — указатель типа char, при инкременте он перемещается на sizeof(char) байт, то есть на 1 байт.
Предположим,ptr— это целочисленный указатель, указывающий на адрес 1000, и это 32-битное целое число. Выполним следующую арифметическую операцию над этим указателем:
ptr++
После выполнения вышеуказанных операцийptrбудет указывать на ячейку 1004, потому что каждый раз, когда ptr инкрементируется, он будет указывать на следующую ячейку целого числа, то есть на 4 байта вперёд от текущей позиции. Эта операция перемещает указатель на следующую ячейку памяти, не затрагивая фактическое значение в этой ячейке памяти. ЕслиptrЕсли он указывает на символ по адресу 1000, вышеуказанная операция заставит указатель указывать на ячейку 1001, потому что следующая позиция символа находится по адресу 1001.
Подведём итог:
- Каждый инкремент указателя фактически заставляет его указывать на ячейку памяти следующего элемента.
- Каждый декремент указателя заставляет его указывать на ячейку памяти предыдущего элемента.
- Количество байтов, на которое указатель смещается при инкременте или декременте, зависит от размера типа данных переменной, на которую он указывает; например, int занимает 4 байта.
Инкремент указателя
Инкремент указателя означает, что указатель начинает указывать на следующую ячейку памяти.
Операция инкремента указателя выполняет соответствующее смещение в памяти на основе типа данных, на который указывает указатель.
В программах мы предпочитаем использовать указатели вместо массивов, потому что переменный указатель можно инкрементировать, а массив инкрементировать нельзя; массив можно рассматривать как константный указатель. Следующая программа инкрементирует переменный указатель, чтобы последовательно обращаться к каждому элементу массива:
Пример
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
存储地址:var[0] = e4a298cc 存储值:var[0] = 10 存储地址:var[1] = e4a298d0 存储值:var[1] = 100 存储地址:var[2] = e4a298d4 存储值:var[2] = 200
Инкремент указателя на символ:
Пример
int main() {
char str[] = "Hello";
char *ptr = str; // Указатель указывает на первый символ строки
printf("Начальный символ: %c\n", *ptr); // Вывести H
ptr++; // Увеличить указатель, чтобы он указывал на следующий символ
printf("Символ после инкремента: %c\n", *ptr); // Вывод e
return 0;
}
В этом примере ptr++ заставляет указатель переместиться из str
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
初始字符: H 递增后字符: e
Инкремент указателя на структуру:
Пример
struct Point {
int x;
int y;
};
int main() {
struct Point points[] = {{1, 2}, {3, 4}, {5, 6}};
struct Point *ptr = points; // Указатель указывает на первый элемент массива структур
printf("Начальная точка: (%d, %d)\n", ptr->x, ptr->y); // Вывод (1, 2)
ptr++; // Инкрементируем указатель, чтобы он указывал на следующую структуру
printf("Точка после инкремента: (%d, %d)\n", ptr->x, ptr->y); // Вывод (3, 4)
return 0;
}
. Поскольку ptr — указатель типа struct Point, при его инкременте он смещается на sizeof(struct Point) байт.
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
初始点: (1, 2) 递增后点: (3, 4)
Декрементирование указателя
Декремент указателя означает, что указатель начинает указывать на предыдущую ячейку памяти. Как и при инкременте указателя, операция декремента также выполняет соответствующее смещение в памяти в зависимости от типа данных, на который указывает указатель.
Выполнение операции декремента для указателя означает вычитание размера в байтах его типа данных из значения, как показано ниже:
Пример
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
初始值: 50 递减后值: 40 再次递减后值: 30
Декремент указателя на символ:
Пример
int main() {
char str[] = "Hello";
char *ptr = &str[4]; // Указатель указывает на последний символ 'o' строки
printf("Начальный символ: %c\n", *ptr); // Вывод o
ptr--; // Уменьшить указатель, чтобы он указывал на предыдущий символ
printf("Уменьшенный символ: %c\n", *ptr); // Вывод l
ptr--; // Снова уменьшить указатель
printf("Уменьшенный символ снова: %c\n", *ptr); // Вывод l
return 0;
}
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
初始字符: o 递减后字符: l 再次递减后字符: l
Уменьшение указателя на структуру:
Пример
struct Point {
int x;
int y;
};
int main() {
struct Point points[] = {{1, 2}, {3, 4}, {5, 6}};
struct Point *ptr = &points[2]; // Указатель указывает на последний элемент массива структур
printf("Начальная точка: (%d, %d)\n", ptr->x, ptr->y); // Вывод (5, 6)
ptr--; // Уменьшить указатель, чтобы он указывал на предыдущую структуру
printf("Уменьшенная точка: (%d, %d)\n", ptr->x, ptr->y); // Вывод (3, 4)
ptr--; // Снова уменьшить указатель
printf("Уменьшенная точка снова: (%d, %d)\n", ptr->x, ptr->y); // Вывод (1, 2)
return 0;
}
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
初始点: (5, 6) 递减后点: (3, 4) 再次递减后点: (1, 2)
Сравнение указателей
В C указатели можно сравнивать, чтобы определить их взаимное расположение. Сравнение указателей в основном используется для определения того, указывают ли два указателя на одну и ту же область памяти, или для определения того, находится ли один указатель перед или после другого указателя.
Указатели можно сравнивать с помощью операторов отношения, таких как==、!=、<、>、<=и>=Если p1 и p2 указывают на две связанные переменные, например на разные элементы одного и того же массива, то p1 и p2 можно сравнивать по величине.
Ниже приведены примеры кода, показывающие, как сравнивать указатели и выводить результаты.
Сравнение указателей на равенство:
Пример
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
ptr1 和 ptr2 指向相同的内存地址 ptr1 和 ptr3 指向不同的内存地址
Сравнение размера указателя:
Пример
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr1 = &arr[1]; // Указывает на arr[1], значение 20
int *ptr2 = &arr[3]; // Указывает на arr[3], значение 40
if (ptr1 < ptr2) {
printf("ptr1 находится перед ptr2\n"); // Эта строка будет выведена
} else {
printf("ptr1 находится после ptr2 или на той же позиции\n");
}
if (ptr1 > ptr2) {
printf("ptr1 находится после ptr2\n");
} else {
printf("ptr1 находится перед ptr2 или на той же позиции\n"); // Эта строка будет выведена
}
return 0;
}
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
ptr1 在 ptr2 之前 ptr1 在 ptr2 之前或相同位置
Перебор массива и сравнение указателей:
Пример
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *start = arr; // Указывает на первый элемент массива
int *end = &arr[4]; // Указывает на последний элемент массива
int *ptr;
for (ptr = start; ptr <= end; ptr++) {
printf("Значение, на которое указывает текущий указатель: %d\n", *ptr);
}
return 0;
}
Когда приведенный выше код скомпилирован и выполнен, он выдает следующие результаты:
当前指针指向的值: 10 当前指针指向的值: 20 当前指针指向的值: 30 当前指针指向的值: 40 当前指针指向的值: 50
Итог
- Сравнение на равенство (
==и!=): Используется для определения, указывают ли два указателя на одну и ту же ячейку памяти. - Сравнение по величине (
<,>,<=,>=): Обычно используется, когда указатели перемещаются по массивам или блокам памяти, чтобы определить, находится ли один указатель до или после другого указателя.