Почему * p ++ отличается от * p + = 1?

Рассмотрим:

void foo1(char **p) { *p++; }
void foo2(char **p) { *p += 1; }

и

char *s = "abcd";
char *a = s; 
foo1(&a); 
printf("%s", a); //abcd

но если я использую foo2() вместо:

char *a = s; 
foo2(&a); 
printf("%s", a); //bcd

Может кто-нибудь объяснить это?

Ответ 1

Ключ - это приоритет оператора += и ++. ++ имеет более высокий приоритет, чем += (фактически, операторы присваивания имеют второй наименьший приоритет в C), поэтому операция

*p++

означает разыменование указателя, затем увеличивать указатель на 1 (как обычно, согласно правилам арифметики указателя, это не обязательно один байт, а скорее sizeof(*p) относительно результирующего адреса), С другой стороны,

*p += 1

означает увеличение значения , указанного указателем одним (и ничего не делать с самим указателем).

Ответ 2

Внеочередные. Постфикс ++ связывает более строгий, чем префикс *, поэтому он увеличивает p. += находится на нижнем конце списка приоритетов вместе с простым оператором присваивания, поэтому он добавляет 1 к *p.

Ответ 3

Приоритет префикса ++ и * тот же. Ассоциативность обоих правых налево. Приоритет postfix ++ выше, чем оба * и prefix ++. Ассоциативность постфикса ++ слева направо.

Ответ 4

Начнем с *p += 1

Я постараюсь ответить на это немного по-другому... Шаг 1 Посмотрим на операторы и операнды: в этом случае это один операнд (указатель p), и у нас есть два оператора: этот случай * для разыменования и + = 1 для приращения. Шаг 2, имеющий более высокий приоритет *, имеет более высокий приоритет над + =


*P++ Это немного сложнее... может быть, даже злой Снова у нас есть один операнд (p указатель) и два оператора, только теперь * для разыменования и постположения ++ имеют одинаковый приоритет. (В некоторых таблицах ++ в сообщении является более высоким приоритетом.)

Шаг 1. Посмотрите на операторы и операнды: в этом случае это операнд, и у вас есть два оператора, в этом случае * для разыменования и ++ для приращения. Шаг 2, который имеет более высокий приоритет? ++ имеет более высокий приоритет над * Примечание: даже если у них есть ИМЕЮЩЕЕ НАЧАЛЬНОЕ УПРАВЛЕНИЕ, они связывают право налево, опять же ++ до * Шаг 3 (сложная часть...) Где ++? он находится в правой части операнда, что означает POST Increment. В этом случае компилятор принимает "умственную заметку" для выполнения приращения ПОСЛЕ, это делается со всеми другие операторы... Что после? Это означает, что он будет применять только приращение как самый последний шаг перед следующим ';' так что это будет сделано со всеми другими операторами, которые находятся на одной и той же линии, примечание: если оно было * ++ p, то оно будет делать это ДО любого другого оператора в той же строке, поэтому в этом случае он эквивалентен взятию двух регистров процессора, один будет удерживать значение разыменованных * p и другой будет удерживать значение приращенного p ++, причиной в этом случае является два, является POST-активностью... Вот здесь в этом случае сложно, и это выглядит как противоречие. Можно было бы ожидать, что ++ будет иметь приоритет над *, что и делает, только то, что POST означает, что он будет применяться только после ВСЕХ других операндов, ПЕРЕД следующей следующей:; маркер...

Как я уже сказал, сложная часть заключается в том, что любое приращение, находящееся справа от операнда, будет отложено и будет применяться как LAST-операция до того, как он перейдет к следующей строке...