Я только начал изучать 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
и ++
? Я думал, что они оба одинаковые.
c
pointers
post-increment
привет нгуен
источник
источник
string
.allocateIntArray
- плохая репутация, поскольку вам кажется, чтоmalloc
это массив из функции, но это не так. Я предлагаюfillIntArray
вместо этого. 2) Вы не используете возвращаемое значениеallocateIntArray
. Я предлагаю вам изменить тип возвращаемого значения наvoid
. 3) Не следует лиif (ptr != NULL)
в функцииincreasePointer
бытьif (*ptr != NULL)
? 4) Отливкаmalloc
не требуется. См. Комментарий Сурава выше. 5) Это:for (int i = 0; i < 10; i++){ printf("%d\n", p1[i]); }
иprintf("%d\n", *p1); p1--;
должно быть заключено вif(p1 != NULL)
. 6)string.h
не используется.p+=1
это нравится++p
, а не нравитсяp++
Ответы:
Разница связана с приоритетом операторов.
Оператор постинкремента
++
имеет более высокий приоритет, чем оператор разыменования*
. Так*ptr++
эквивалентно*(ptr++)
. Другими словами, приращение поста изменяет указатель, а не то, на что он указывает.Оператор присваивания
+=
имеет более низкий приоритет, чем оператор разыменования*
, поэтому*ptr+=1
эквивалентен(*ptr)+=1
. Другими словами, оператор присваивания изменяет значение, на которое указывает указатель, и не изменяет сам указатель.источник
*p++
и*++p
. Операторный приоритет последнего очевиден, далее следует первый.Порядок приоритета для 3 операторов, задействованных в вашем вопросе, следующий:
постинкремент
++
> разыменование*
> присвоение+=
Вы можете проверить эту страницу для получения дополнительной информации по этому вопросу.
Короче говоря, для того, чтобы выразить это присвоение
*ptr+=1
с помощью оператора постинкремента, вам необходимо добавить скобки к оператору разыменования, чтобы дать этой операции приоритет перед,++
как в этом(*ptr)++
источник
Давайте применим круглые скобки, чтобы показать порядок операций
Сделаем это снова с
И снова с
*ptr += 1
, мы увеличиваем значение переменной нашего указателя указывает .*ptr++
, мы увеличиваем указатель после выполнения всего нашего оператора (строки кода) и возвращаем ссылку на переменную, на которую указывает наш указатель. .Последний позволяет делать такие вещи, как:
Это распространенный метод, используемый для копирования
src
массива в другойdest
массив.источник
Очень хороший вопрос.
В K&R "Язык программирования C" "5.1 Указатели и адреса" мы можем получить ответ на этот вопрос.
«Унарные операторы * и & связываются сильнее, чем арифметические операторы»
«Унарные операторы, такие как * и ++, связывают справа налево ».
// Работает как * (ptr ++).
Правильный способ:
источник
* ptr + = 1: увеличивать данные, на которые указывает ptr. * ptr ++: указатель увеличения, указывающий на следующую ячейку памяти вместо данных, на которые указывает указатель.
источник