Se uma function não retorna nenhum valor, com um tipo de retorno válido, é aceitável que o compilador jogue lixo?

Se uma function tem um tipo de retorno diferente de void , e a function não retorna nada, então eu acho que o compilador retorna um valor de lixo (possivelmente visto como um valor não inicializado). Isso acontece em tempo de compilation, então por que não deveria lançar um erro?

Por exemplo,

 int func1() { return; // error } int func2() { // does not return anything } 

O segundo func2 deve lançar um erro, mas isso não acontece. Existe uma razão para isso? Meu pensamento era tal que, pode ser visto como um valor não inicializado, então se precisarmos lançar um erro no segundo caso, então precisamos lançar um erro, se um valor não for inicializado, digamos

  int i; // error int i = 6; // okay 

Alguma idéia, ou isso é uma pergunta duplicada? Eu aprecio sua ajuda.

Em C ++, esse código tem comportamento indefinido:

[stmt.return] / 2 … Fluir do final de uma function é equivalente a um retorno sem valor; isso resulta em comportamento indefinido em uma function de retorno de valor. …

A maioria dos compiladores produzirá um aviso para código semelhante ao da pergunta.

O padrão C ++ não exige que isso seja um erro de tempo de compilation porque, no caso geral, seria muito difícil determinar corretamente se o código realmente é executado no final da function ou se a function sai por meio de uma exceção (ou um longjmp ou mecanismo similar).

Considerar

 int func3() { func4(); } 

Se func4() lançar, então este código está totalmente bem. O compilador pode não ser capaz de ver a definição de func4() (por causa da compilation separada) e, portanto, não pode saber se ele será lançado ou não.

Além disso, mesmo que o compilador possa provar que func4() não lança, ele ainda teria que provar que func3() realmente é chamado antes de poder legitimamente rejeitar o programa. Tal análise requer inspeção de todo o programa, que é incompatível com a compilation separada, e que nem é possível no caso geral.

Em C, citando N1256 6.9.1p12:

Se o } que termina uma function for atingido e o valor da chamada de function for usado pelo chamador, o comportamento será indefinido.

Portanto, é legal (mas uma má idéia) para uma function não-vazia falhar ao retornar um valor, mas se isso acontecer e o chamador tentar usar o resultado, o comportamento é indefinido. Note que não necessariamente apenas retorna algum valor arbitrário; no que diz respeito ao padrão, tudo é possível.

O Pre-ANSI C não tinha a palavra-chave void , portanto, a maneira de escrever uma function que não retornava um valor era deixar de fora o tipo de retorno, fazendo com que ele retornasse implicitamente. A exigência de uma instrução de return em uma function de retorno de valor teria quebrado o código antigo. Ele também exigiria uma análise extra do compilador para determinar se todos os caminhos de código atingiram uma instrução de return ; tal análise é razoável para os compiladores modernos, mas pode ter sido um fardo excessivo quando C foi padronizado pela primeira vez.

C ++ é um pouco mais rigoroso. Em C ++:

Fluir do final de uma function é equivalente a um retorno sem valor; isso resulta em comportamento indefinido em uma function de retorno de valor.

então o comportamento é indefinido se o chamador tentar usar o resultado (inexistente) ou não.

Os compiladores C e C ++ certamente podem avisar sobre instruções de return ausentes ou sobre caminhos de controle que caem no final de uma function sem executar uma instrução de return , mas os respectivos padrões não exigem que eles façam isso.

Em C, é legal que uma function não vazia seja concluída sem retornar um valor, contanto que o código de chamada não tente usar o valor de retorno .

Por outro lado, uma declaração de return sem uma expressão não pode aparecer em uma function não-vazia.

As partes relevantes da norma C99 são §6.9.1 para o primeiro caso:

Se o } que termina uma function for atingido e o valor da chamada de function for usado pelo chamador, o comportamento será indefinido.

e §6.8.6.4 para o segundo caso:

Uma declaração de return sem uma expressão só deve aparecer em uma function cujo tipo de retorno é void .

Ambas as suas funções estão mal formadas. A diferença entre eles é que o seu func1 viola as regras sobre como a declaração de return pode ser usada enquanto o func2 é um comportamento indefinido. A instrução de return no seu func1 é ilegal e uma implementação deve diagnosticar isso. A falta de uma declaração de retorno na sua func2 é um comportamento indefinido. A maioria dos compiladores vai diagnosticar isso, mas nenhum precisa fazer isso.