предупреждение в кодовых блоках, «операция может быть неопределенной» - PullRequest
0 голосов
/ 07 июня 2019

Я получаю предупреждение, а не ошибку, и когда я игнорирую это предупреждение и в любом случае собираю / запускаю, мой код работает нормально. Я все еще волнуюсь из-за предупреждения, или, может быть, я просто хочу его понять.

Эта функция добавляет один символ в начало строки.

void s_pfx(char pf, char *s){

    i = -1;
    while(s[++i]);
    s[i + 1] = '\0';

    while(i)
        s[i] = s[--i];

    s[i] = pf;
}

Предупреждение в цикле while, когда я предварительно уменьшаю i. (У меня есть я как глобальная переменная.)

Предупреждение: «предупреждение: операция над« i »может быть неопределенной [-Wsequence-point]»

Я могу это исправить, используя

while(i){
    s[i] = s[i - 1];
    i--;
}

но почему я должен делать это таким образом? Кажется, что это съело бы время, возможно наносекунды, но это прибавит.

Я не понимаю, почему компилятор не может понять код. Это кажется довольно четким для меня. Я посмотрел на некоторые другие подобные вопросы / ответы, но это кажется намного проще.

Помощь! Спасибо.

1 Ответ

3 голосов
/ 07 июня 2019

Ошибка действительно в выражении s[i] = s[-- i].

Спецификация C требует, чтобы некоторые операторы действовали как «точки последовательности», то есть чтобы их первый операнд был полностью оценен перед вторым. Оператор =, однако, не является - это означает, что компилятор может вычислять выражение в любом порядке.

Это не проблема, когда вы делаете что-то вроде i = i + 3, потому что левый знак назначения не оценивается (он записывается, а не читается). Но вы используете указатели там. s[i] действительно означает *(s + i) в C; скобки синтаксис сахар.

Так что у вас действительно есть *(s + i) = *(s + --i) там. И это выражение читает i в левой части (оно должно вычислять сумму для вычисления адреса, по которому будут храниться данные), и записывает в i в правой части (--i). И нет никакого определенного порядка оценки, потому что = не является точкой последовательности.

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

...