Разница между * ptr + = 1 и * ptr ++ в C
Я только начал изучать C, и, когда я делал один пример о передаче указателя на указатель в качестве параметра функции, я обнаружил проблему.
Это мой пример кода:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int* allocateIntArray(int* ptr, int size){
if (ptr != NULL){
for (int i = 0; i < size; i++){
ptr[i] = i;
}
}
return ptr;
}
void increasePointer(int** ptr){
if (ptr != NULL){
*ptr += 1; /* <----------------------------- This is line 16 */
}
}
int main()
{
int* p1 = (int*)malloc(sizeof(int)* 10);
allocateIntArray(p1, 10);
for (int i = 0; i < 10; i++){
printf("%d\n", p1[i]);
}
increasePointer(&p1);
printf("%d\n", *p1);
p1--;
free(p1);
fgets(string, sizeof(string), stdin);
return 0;
}
Проблема возникает в строке 16, когда я изменяю *ptr+=1
на *ptr++
. Ожидаемым результатом должен быть весь массив и номер 1, но когда я использую *ptr++
, результат равен 0.
Есть ли разница между +=1
и ++
? Я думал, что они оба одинаковы.
Ответы
Ответ 1
Разница связана с приоритетом оператора.
Оператор post-increment ++
имеет более высокий приоритет, чем оператор разыменования *
. Итак, *ptr++
эквивалентно *(ptr++)
. Другими словами, приращение post изменяет указатель, а не то, на что он указывает.
Оператор присваивания +=
имеет более низкий приоритет, чем оператор разыменования *
, поэтому *ptr+=1
эквивалентен (*ptr)+=1
. Другими словами, оператор присваивания изменяет значение, на которое указывает указатель, и не меняет сам указатель.
Ответ 2
Порядок приоритета для трех операторов, участвующих в вашем вопросе, следующий:
post-increment ++
> разыменование *
> назначение +=
Подробнее об этом можно узнать на странице .
При анализе выражения оператор, который указан в некоторой строке, будет привязан к его аргументам более жестко (как в скобках), чем к любому оператору, который указан ниже в строке. Например, выражение *p++
анализируется как *(p++)
, а не как (*p)++
.
Короче говоря, чтобы выразить это назначение *ptr+=1
с помощью оператора post-increment, вам нужно добавить скобки к оператору разыменования, чтобы присвоить этому приоритету операции над ++
, как в этом (*ptr)++
Ответ 3
Позвольте применить круглые скобки, чтобы показать порядок операций .
a + b / c
a + (b/c)
Сделайте это снова с помощью
*ptr += 1
(*ptr) += 1
И снова с
*ptr++
*(ptr++)
- В
*ptr += 1
мы увеличиваем значение переменной, на которую указывает наш указатель.
- В
*ptr++
мы увеличиваем указатель после завершения всей нашей инструкции (строки кода) и возвращаем ссылку на переменную, на которую указывает наш указатель.
Последнее позволяет вам делать такие вещи, как:
for(int i = 0; i < length; i++)
{
// Copy value from *src and store it in *dest
*dest++ = *src++;
// Keep in mind that the above is equivalent to
*(dest++) = *(src++);
}
Это общий метод, используемый для копирования массива src
в другой массив dest
.
Ответ 4
Очень хороший вопрос.
В языке программирования K & R "C" "5.1 Указатели и адреса" мы можем получить ответ для этого.
"Унарные операторы * и и связывают более жестко, чем арифметические операторы"
*ptr += 1 //Increment what ptr points to.
"Унарные операторы, такие как * и ++, ассоциируют справа налево."
*ptr++ //Increment prt instead of what ptr point to.
//Он работает как * (ptr ++).
Правильный способ:
(*ptr)++ //This will work.
Ответ 5
* ptr + = 1: Приращение данных, на которые указывает ptr.
* ptr ++: указатель увеличения, указывающий на следующую ячейку памяти вместо данных, на которые указывает указатель.