Почему gcc не выдает предупреждение при неопределенном поведении в коде внутри? - PullRequest
7 голосов
/ 26 ноября 2011

Я только что прочитал этот SO C ++ FAQ о неопределенном поведении и точках последовательности и немного поэкспериментировал. В следующем коде gcc-4.5.2 выдает мне предупреждение только в строке, упомянутой в комментарии к коду, хотя в предыдущей строке тоже показано неопределенное поведение, не так ли? Вы не можете сказать, какой операнд сложения выполняется первым (так как + не является точкой последовательности). Почему gcc тоже не выдает предупреждение в этой строке?

int i=0;
int j=0;

int foo(void) {
    i=1;
    return i;
}

int main(void) {
    i = i + foo(); 
    j = j + (j=1); //Here is a rightly warning
    return 0;
}

Спасибо за помощь.

Ответы [ 3 ]

16 голосов
/ 26 ноября 2011

Поведение i = i + foo (); не указано, но не определено Undefined означает, что разрешено любое возможное поведение, даже прерывание программы. Unspecified означает, что либо i вычисляется первым, либо foo (). Да, foo пишет в тот же i, но, поскольку это происходит в отдельном операторе, существует точка последовательности до и после этого хранилища.

1 голос
/ 26 ноября 2011

Строка i = i + foo(); в вашей программе не определена, но не определена.

Компиляторы пытаются выдавать предупреждения без ложных срабатываний (каждый раз, когда компилятор предупреждает, есть дефект, который должен исправить программист) или, по крайней мере, с очень низким уровнем ложных срабатываний. Это значит, что взамен у них немало ложных негативов. В соответствии с той же философией, компиляторы обычно не предупреждают о неопределенном поведении.

Чтобы получить предупреждение о вашей программе, вы должны изучить статические анализаторы, которые более агрессивны в отношении предупреждений, за счет чуть большего количества ложных срабатываний. Статические анализаторы могут очень хорошо решить, чтобы предупредить о неопределенном поведении. Некоторые из них даже предупреждают об определенных поведениях, которые, хотя и определены, указывают на то, что программист, вероятно, был сбит с толку.

0 голосов
/ 26 ноября 2011

Для людей очевидно, что вызов foo () изменит i, но для компьютерной программы это трудно увидеть.Это просто не предназначено, чтобы видеть это.

...