Является ли ++ таким же, как + = 1 для указателей?
Я бы хотел реорганизовать какой-то старый C-код, и мне было любопытно, могу ли я заменить все ptr++
на ptr += 1
, где ptr
- некоторый указатель, не изменяя никакого поведения. Вот пример того, что я имею в виду, из K & R Section 5.3:
/* strlen: return length of string s*/
int strlen(char *s)
{
int n;
for (n = 0; *s != '\0'; s++)
n++;
return n;
}
Когда я заменяю s++
на s += 1
, я получаю те же результаты, но мне интересно, будет ли это иметь место для всех типов. Я также сделал тест для int
s:
int size = 10;
int *int_array = (int*)calloc(size, sizeof(int));
for (int i = 0; i < size; i++)
int_array[i] = i;
for (int i = 0; i < size; i++) {
printf("*int_array = %d\n", i, *int_array);
int_array++;
}
Если я заменю строку int_array++;
на int_array += 1;
, я получаю тот же результат.
Подумав об этом еще немного, я понимаю, что может быть проблема, если значение используется в выражении. Было бы безопаснее, я просто переместил приращение на другую строку следующим образом:
int a = 5;
int b = a++;
станет:
int a = 5;
int b = a;
a += 1;
Заключение
То, что я думал, может быть проблемой, увеличивая указатели на разные типы, не является проблемой. См. Ответ @bdonlan по этой причине.
Это не означает, что вы можете заменить все x++
на x += 1
и ожидать такого же поведения. Однако вы можете безопасно заменить ++x
на (x += 1)
, так как они эквивалентны.
Ответы
Ответ 1
a += 1
эквивалентен ++a
(C99 §6.5.3.1/2). В строке, подобной int b = a++;
, это означает, что она не эквивалентна a++
; a++
вернет старое значение a
, а a += 1
возвращает новое значение.
Обратите внимание, что если вы не используете результат a++
(т.е. вы имеете оператор, содержащий только a++;
), то они фактически идентичны.
Кроме того, обратите внимание, что арифметика _all указателя выполняется с шагом в размере заостренного типа (§6.5.6/8). Это означает, что:
ptr = ptr + x;
эквивалентно:
ptr = (ptr_type *)( (char *)ptr + x * sizeof(*ptr) );
Это то же самое, если вы используете +
, ++
, +=
или []
(p[x]
в точности эквивалентно *(p + x)
; вы можете даже делать такие вещи, как 4["Hello"]
из-за этого).
Ответ 2
++
и --
определяется в терминах арифметики для встроенных типов. Поведение будет таким же, кроме постфикса, возвращающего старое значение.
Ответ 3
Это хороший вопрос. Ответ - да, вы можете это сделать - независимо от того, как вы это делаете, приращение указателя добавляет sizeof(the type that the pointer points to)
к указателю. Как указывают другие ответы, вам нужно быть осторожным, чтобы вы не зависели от того, когда происходит приращение, то есть, как ++, так и ++ a имеют другой эффект, но в конечном итоге заканчивается тем же значением.
Вопрос: почему вы хотите изменить весь свой код от a++
до a+=1
? Использование оператора post-increment с указателями - это то, что должно легко понять любой программист на C, поэтому трудно понять, почему вы это сделаете.