Является ли ++ таким же, как + = 1 для указателей? - программирование

Является ли ++ таким же, как + = 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), так как они эквивалентны.

4b9b3361

Ответ 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, поэтому трудно понять, почему вы это сделаете.