Почему нет ошибки компилятора, когда оператора return нет? - PullRequest
15 голосов
/ 07 июня 2011

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

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

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

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

Ответы [ 7 ]

12 голосов
/ 07 июня 2011

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

 warning: control reaches end of non-void function

РЕДАКТИРОВАТЬ : или, более конкретно, -Wreturn-type.

9 голосов
/ 07 июня 2011

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

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

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

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

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

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

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

#include <iostream>

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

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

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

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

1 голос
/ 26 июля 2018

Вы можете преобразовать предупреждение в ошибку, используя следующие параметры компилятора

-Wreturn-type -Werror=return-type.

Проверьте эту ссылку

1 голос
/ 07 июня 2011

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

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

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

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

    case 0x80:
        return -1;

    case 0xC0:
        return 1;
    }
}

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

1 голос
/ 07 июня 2011

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

0 голосов
/ 07 июня 2011

Стандарт говорит об этом виде программирования, что он производит неопределенное поведение .

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...