++ такой же, как + = 1 для указателей? - PullRequest
6 голосов
/ 07 декабря 2011

Я хотел бы провести рефакторинг своего старого C-кода, и мне было любопытно, смогу ли я заменить все ptr++ на ptr += 1, где ptr - некоторый указатель без изменения поведения. Вот пример того, что я имею в виду, из раздела 5.3 K & R:

/* 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), поскольку они эквивалентны.

Ответы [ 3 ]

12 голосов
/ 07 декабря 2011

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"].

1 голос
/ 07 декабря 2011

Хороший вопрос.Ответ - да, вы можете сделать это - независимо от того, как вы это делаете, увеличение указателя добавляет sizeof(the type that the pointer points to) к указателю.Как показывают другие ответы, вам нужно быть осторожным, чтобы не зависеть от , когда происходит приращение, то есть a ++ и ++ a имеют разный эффект, но в конечном итоге заканчиваются тем же значением.

Вопрос: почему вы хотите изменить весь свой код с a++ на a+=1?Использование оператора постинкремента с указателями - это то, что должен легко понять любой программист на C, поэтому трудно понять, почему вы сделали это изменение.

1 голос
/ 07 декабря 2011

++ и -- определены в терминах арифметики для встроенных типов.Поведение будет таким же, за исключением постфикса, возвращающего старое значение.

...