То, почему “не все пути управления возвращают значение”, предупреждает и не ошибка?

Настройки являются стандартными парами "ключ-значение" (строковая строка). Я мог обернуть их в XML-файл, если это помогает.

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

28
задан Community 23 May 2017 в 10:29
поделиться

3 ответа

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

Причина этого, насколько я могу судить, в основном историческая.

Изначально в C не было void и неявного int означало, что большинство функций возвращали int , если явно не объявлено, что возвращают что-то еще, даже если не было намерения использовать возвращаемое значение.

Это означает, что многие функции возвращали int, но без явной установки a возвращаемое значение, но это было нормально, потому что вызывающие абоненты никогда не использовали возвращаемое значение для этих функций.

Некоторые функции действительно возвращали значение, но использовали неявное int , потому что int был подходящим типом возврата.

Это означает, что pre- void В коде было множество функций, которые номинально возвращали int , но которые можно было объявить как возвращающие void и множество других функций, которые должны возвращать int без четкого способа объясни разницу. Применение return во всех путях кода всех функций, не являющихся void , на любом этапе приведет к нарушению унаследованного кода.

Также есть аргумент, что некоторые пути кода в функции могут быть недоступны но это может быть нелегко определить с помощью простого статического анализа, так зачем же принудительно применять ненужный возврат ?

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

Это означает, что код до void имел множество функций, которые номинально возвращали ] int , но который может быть объявлен как возвращающий void и множество других функций, которые должны возвращать int без четкого способа отличить разницу. Применение return во всех путях кода всех функций, не являющихся void , на любом этапе приведет к нарушению унаследованного кода.

Также есть аргумент, что некоторые пути кода в функции могут быть недоступны но это может быть нелегко определить с помощью простого статического анализа, так зачем же принудительно применять ненужный возврат ?

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

Это означает, что код до void имел множество функций, которые номинально возвращали ] int , но который может быть объявлен как возвращающий void и множество других функций, которые должны возвращать int , без четкого способа определить разницу. Применение return во всех путях кода всех функций, не являющихся void , на любом этапе приведет к нарушению унаследованного кода.

Также есть аргумент, что некоторые пути кода в функции могут быть недоступны но это может быть нелегко определить с помощью простого статического анализа, так зачем же принудительно применять ненужный возврат ?

Это означает, что код до void имел множество функций, которые номинально возвращали int , но которые можно было объявить для возврата void и множества других функций, которые должен возвращать int без четкого определения разницы. Применение return во всех путях кода всех функций, не являющихся void , на любом этапе приведет к нарушению унаследованного кода.

Также есть аргумент, что некоторые пути кода в функции могут быть недоступны но это может быть непросто определить с помощью простого статического анализа, так зачем же принудительно использовать ненужный возврат ?

Это означает, что код до void имел множество функций, которые номинально возвращали int , но которые можно было объявить для возврата void и множества других функций, которые должен возвращать int без четкого определения разницы. Применение return во всех путях кода всех функций, не являющихся void , на любом этапе приведет к нарушению унаследованного кода.

Также есть аргумент, что некоторые пути кода в функции могут быть недоступны но это может быть непросто определить с помощью простого статического анализа, так зачем же принудительно использовать ненужный возврат ?

30
ответ дан 28 November 2019 в 03:26
поделиться

Я предполагаю, что это всего лишь предупреждение, потому что компилятор не всегда может быть на 100% уверен, что можно не выполнить возврат.

то есть, если у вас есть:


-= source1.c =-
int func()
{
    if(doSomething())
    {
       return 0;
    }
}

-= source2.c =-
int doSomething()
{
    return 1;
}

Компилятор в этом случае может не знать, что он всегда будет возвращать, но вы это делаете. Конечно, это ужасная практика программирования - полагаться на знание того, как работает внешний код.

Что касается того, что на самом деле будет возвращено, это зависит от платформы. На x86 ABI EAX используется для возвращаемого значения (до 32 бит), поэтому он будет возвращать то, что когда-либо было помещено в этот регистр (что может быть возвращением из чего-то еще, временного значения или полного мусора).

9
ответ дан 28 November 2019 в 03:26
поделиться

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

-2
ответ дан 28 November 2019 в 03:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: