операция над «i» может быть неопределенной

У меня есть этот код, чтобы взять строку формы bla_2 и разделить ее:

void separate(char* str, char* word, int* n) {
    int i = 0;
    while(str[i] != '_') {
        word[i] = str[i++];
    }
    *n = str[++i] - '0';
}

Я получил:

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

Но я только меняю i через оператора ++, ничего не присваиваю.

Итак, зачем УБ, если он есть? Если нет, то как избавиться от предупреждения?

Обратите внимание, что, по моему мнению, этот вопрос касается другой проблемы.


person gsamaras    schedule 16.11.2014    source источник
comment
@ Rizier123: это ничего не изменит в отношении точек последовательности.   -  person Oliver Charlesworth    schedule 16.11.2014


Ответы (2)


word[i] = str[i++]; это проблема.

Это выбор компилятора, если i в word[i] является доступом до или после увеличения i в str[i++];

Выполните i++ после задания

word[i] = str[i];
i++;

Дальше while(str[i] != '_') скорее всего должно быть

while(str[i] != '_' && str[i] != '\0')

для предотвращения переполнения буфера.

person chux - Reinstate Monica    schedule 16.11.2014
comment
Под исправлением я имел в виду, что это не UB, но да, я понял. - person gsamaras; 16.11.2014
comment
Это выбор компилятора... доступ до или после Строго говоря, код может делать что угодно, кроме этих двух вариантов. - person AlexD; 16.11.2014
comment
Кроме того, этот код не ставит нулевой терминатор в строку. Я понимаю твою точку зрения @AlexD, спасибо тебе тоже. - person gsamaras; 17.11.2014
comment
@AlexD Что ты имеешь в виду, я не могу понять. - person Suraj Jain; 13.02.2017
comment
@SurajJain Это UB, так что все ставки сняты. - person AlexD; 13.02.2017

Причина в том, что обе стороны присваивания зависят от значения i, однако вы изменяете i в операторе, и между двумя использованиями i нет точки последовательности. В соответствии со стандартом C это приводит к неопределенному поведению.

Чтобы исправить это предупреждение, измените соответствующую строку на

word[i] = str[i];
i++;

Кстати, вы могли бы использовать указатели вместо явных индексов, что, вероятно, сделало бы код немного более читабельным:

void separate(char* str, char* word, int* n) {
    while(*str != '_') {
        *word++ = *str++;
    }

    *n = *++str - '0';
}
person The Paramagnetic Croissant    schedule 16.11.2014
comment
+1 за предложение указателя, но я принимаю другой ответ, потому что он пришел первым. :) - person gsamaras; 16.11.2014
comment
@G.Samaras Самая быстрая пушка на Западе - person The Paramagnetic Croissant; 17.11.2014
comment
Спасибо за ссылку, интересно! - person gsamaras; 17.11.2014