Почему этот фрагмент кода не меняет строку?

Я смотрю на строковые манипуляции в C, и я не понимаю, почему оператор s1[i] = s1[++i]; не заменит первый H на следующий символ e. Взгляните на код:

#include <stdio.h>

main()
{
  char s1[] = "Hello world !";
  for(int i = 0; s1[i] != '\0'; ++i)
    s1[i] = s1[++i];
  printf("%s", s1);
}

Он печатает Hello world ! вместо el r

Ответ 1

В вашей программе undefined поведение, потому что в этом утверждении

s1[i] = s1[++i];

i дважды изменяется между точками последовательности (оператор присваивания = не вводит точку последовательности).

gcc (gcc -Wall -Wextra) предупреждает:

warning: operation on ‘i’ may be undefined [-Wsequence-point]

аналогично clang предупреждает:

warning: unsequenced modification and access to 'i' [-Wunsequenced]

Ответ 2

undef.c: In function ‘main’:
undef.c:7:24: warning: operation on ‘i’ may be undefined [-Wsequence-point]
             s1[i] = s1[++i];
                        ^~~

Включите предупреждения компилятора и обратите внимание на них. Компилятор - ваш друг.

Что означает это предупреждение:

В C нет правила, говорящего, какую сторону назначения следует оценить сначала. В этом случае кажется, что правая сторона сначала оценивалась, но в целом результат будет undefined.