Возвращать тип void в C и С++
Это компиляция без каких-либо предупреждений.
Является ли это законным в C и С++ или он просто работает в gcc и clang?
Если это законно, это что-то новое после C99?
void f(){
}
void f2(){
return f();
}
Обновление
как "Rad Lexus" предложил я попробовал это:
$ gcc -Wall -Wpedantic -c x.c
x.c: In function ‘f2’:
x.c:7:9: warning: ISO C forbids ‘return’ with expression, in function returning void [-Wpedantic]
return f();
$ clang -Wall -Wpedantic -c x.c
x.c:7:2: warning: void function 'f2' should not return void expression [-Wpedantic]
return f();
^ ~~~~~
1 warning generated.
$ gcc -Wall -Wpedantic -c x.cc
(no errors)
$ clang -Wall -Wpedantic -c x.cc
(no errors)
Обновление
Кто-то спросил, как эта конструкция помогает. Ну есть более-менее синтаксический сахар. Вот один хороший пример:
void error_report(const char *s){
printf("Error %s\n", s);
exit(0);
}
void process(){
if (step1() == 0)
return error_report("Step 1");
switch(step2()){
case 0: return error_report("Step 2 - No Memory");
case 1: return error_report("Step 2 - Internal Error");
}
printf("Processing Done!\n");
}
Ответы
Ответ 1
C11, 6.8.6.4 "Оператор return
":
Оператор A return
с выражением не должен появляться в функции, тип возврата которой void
.
Нет, вы не можете использовать выражение, даже если оно имеет тип void
.
Из предисловия того же документа:
Основные изменения во втором издании включали:
[...]
-
return
без выражения, не разрешенного в функции, которая возвращает значение (и наоборот)
Итак, это было изменение от C89 → C99 (второе издание языкового стандарта) и так было с тех пор.
С++ 14, 6.6.3 "Оператор return
":
Оператор return с выражением не-void-типа может использоваться только в функциях, возвращающих значение [...] Оператор return с выражением типа void может использоваться только в функциях с возвращаемым типом cv недействительным; выражение оценивается непосредственно перед тем, как функция вернется к вызывающему.
Да, вы можете использовать выражение, если оно имеет тип void (который был действителен с С++ 98).
Ответ 2
Этот код разрешен в C++
, но не разрешен в C
От Оператор возврата @cppreference
В функции, возвращающей void, оператор return с выражением может если тип выражения недействителен.
OTOH в спецификации C11 проекта n1570:
Основные изменения во втором издании включали:
return без выражения, не разрешенного в функции, которая возвращает значение (и наоборот)
(return
с выражением, не разрешенным в функции, которая возвращает void
)
и 6.8.6.4 return
Оператор return с выражением не должен появляться в функции чей тип возврата недействителен. Оператор return без выражения должен появляться только в функции, тип возврата которой недействителен.
(даже если выражение оценивается как void
)
Ответ 3
С++ позволяет что-то вроде этого:
void f()
{
return void();
}
Пока C не делает. Вот почему предупреждение выдается, если вы скомпилируете его ISO C, а не ISO С++. Это формально описывается как:
Оператор return с выражением типа void может использоваться только в функции с возвращаемым типом cv void
Ответ 4
ISO/IEC 9899: 201x. В проекте Комитета говорится следующее:
6.8.6.4 Оператор return
Ограничения
- Оператор
-
return
с выражением не должен появляться в функции, тип возврата которой void
.
Оператор A return
без выражения должен появляться только в функция, тип возврата которой void
.
Таким образом, это запрещено в C.
Вам нужно использовать переключатель -pedantic
на gcc
, чтобы жаловаться на стандартные нарушения:
test.c: In function ‘f2’:
test.c:6:12: warning: ISO C forbids ‘return’ with expression, in function returning void
[-Wpedantic]
return f();
Ответ 5
Стандарт C не поддерживает эту конструкцию:
C11 6.8.6.4: Оператор return
Ограничения
1 Оператор return
с выражением не должен появляться в функции, тип возврата которой void
. Оператор return
без выражения должен появляться только в функции, тип возврата которой void
.
Никаких специальных положений для специального случая в вопросе не добавляется. Некоторые компиляторы C поддерживают это как расширение (gcc
does, если не указано, что он соответствует одному из стандартов C), но C11 и предыдущие версии считают это нарушением ограничения.