Почему нет ошибки компилятора, когда оператор возврата отсутствует?

В отличие от Java, в C/ C++ следующее разрешено:

int* foo ()
{
  if(x)
    return p;
// what if control reaches here
}

Это часто вызывает сбои и проблемы с отладкой. Почему стандарт не обеспечивает выполнение окончательного возврата для функций non- void? (Компиляторы генерируют ошибку для неправильного значения return)

Есть ли какой-либо флаг в gcc/msvc для обеспечения этого? (что-то вроде -Wunused-result)

Ответ 1

Не разрешено (undefined поведение). Однако стандарт не требует диагностики в этом случае.

Стандарт не требует, чтобы последний оператор был return из-за такого кода:

while (true) {
  if (condition) return 0;
}

Это всегда возвращает 0, но немой компилятор его не видит. Обратите внимание, что стандарт не требует интеллектуальных компиляторов. Оператор return после блока while был бы отходом, который немой компилятор не смог бы оптимизировать. Стандарт не хочет требовать от программиста писать код отходов только для удовлетворения немого компилятора.

g++ -Wall достаточно умен, чтобы испускать диагностику на моей машине.

Ответ 2

Используйте флаг -Wall в gcc.

 warning: control reaches end of non-void function

EDIT: или более конкретно -Wreturn-type.

Ответ 3

Мое предположение: потому что иногда программист знает лучше, чем компилятор. С помощью этого простого примера ясно, что someting является неправильным, но рассмотрите переключатель из многих значений или многих проверок в целом. Вы, как кодер, знаете, что некоторые значения просто не будут переданы функции, но компилятор не делает и просто намекает на вас, что может быть что-то не так.

#include <iostream>

int foo(){
    if(false)
        return 5;
}

int main(){
    int i = foo();
    std::cout << i;
}

Обратите внимание, что четный уровень предупреждения 1 на MSVC дает следующее предупреждение:

предупреждение C4715: 'foo': не все пути управления возвращают значение

Ответ 4

AFAIR Visual Studio 2008 предупреждает вас о "пути выполнения, который не имеет возвращаемого значения". Это допускается по смыслу того, что "C++ не помешает вам стрелять в ногу". Поэтому вы должны думать, а не компилятор.

Ответ 5

Очевидный ответ: потому что это не ошибка. Это только ошибка, если x является ложным, и если вызывающий абонент использует возвращаемое значение, ни один из которых может быть обязательно определен компилятором, по крайней мере, в общем случай.

В этом конкретном случае (возвращении указателя), это не было бы слишком трудно потребовать a return для всех путей; Java делает это. В вообще говоря, это не разумно в C++ требовать этого, поскольку в C++, вы можете вернуть определенные пользователем типы, для которых может быть невозможно построить значение (нет конструктора по умолчанию и т.д.). Таким образом, мы имеем ситуация, когда программист не может предоставить return в ветке, которую он или она знает, не может быть взят, а компилятор не может определить, что ветвь не может быть взята.

Большинство компиляторов будут предупреждать в таких случаях, когда он может определить поток. Все из тех, что я видел, также предупреждают в некоторых случаях, когда это ясно однако невозможно отпасть от конца. (Оба g++ и V C++ предупреждают о:

int
bar( char ch )
{
    switch ( ch & 0xC0 ) {
    case 0x00:
    case 0x40:
        return 0;

    case 0x80:
        return -1;

    case 0xC0:
        return 1;
    }
}

по крайней мере, с обычными параметрами. Хотя совершенно ясно, что это функция никогда не падает с конца.)

Ответ 6

Что говорит стандарт об этом виде программирования, так это то, что он создает поведение undefined.

Undefined поведение - это радость и жалость C/ C++, но это также фундаментальная особенность дизайна языка, которая позволяет многим из оптимизаций уровня low-, которые делают C своего рода "высоким уровнем" ассемблер "(это не так, а просто для того, чтобы дать вам представление).

Итак, хотя перенаправление на John отвечает на вопрос о переключении для использования с GCC, чтобы знать "почему", стандарт не мешает этому, я бы указал на очень интересный анализ поведения undefined и всех его ошибок: Что должен знать каждый программист C о undefined Поведение. Это дает очень поучительное чтение.