Можно написать код, который гарантированно всегда будет возвращать значение, но компилятор может не понять это. Один тривиальный пример будет:
int func(int x)
{
if(x > 0)
return 1;
else if(x == 0)
return 0;
else if(x < 0)
return -1;
}
Что касается компилятора, вполне возможно, что все операторы 3 if
оцениваются как false
, и в этом случае управление падает с конца функции, возвращая неопределенный результат. Однако математически мы знаем, что это невозможно, поэтому эта функция определила поведение.
Да, умный компилятор мог бы понять это, но представьте, что при целочисленных сравнениях у нас были вызовы внешних функций, определенных в отдельной единице перевода. Затем, как люди, мы можем доказать, что все пути управления возвращают значения, но компилятор, конечно, не может этого понять.
Причина, по которой это разрешено, заключается в совместимости с C, а причина, по которой это допускает C, - совместимость с унаследованным кодом C, который был написан до стандартизации C (до ANSI). Был код, который делал именно это, поэтому, чтобы такой код оставался действительным и безошибочным, стандарт C допускал это. Однако позволить элементу управления покинуть функцию без возврата значения - все еще неопределенное поведение.
Любой достойный компилятор должен предоставить предупреждение об этом; в зависимости от вашего компилятора вам, возможно, придется повысить уровень предупреждения. Я считаю, что опция для этого предупреждения с gcc - -Wextra
, которая также включает в себя кучу других предупреждений.