Por que o 'main' não pode retornar um double ou String ao invés de int ou void?

38

Em muitos idiomas, como C, C ++ e Java, o main method / function tem um tipo de retorno de void ou int , mas não double ou String . Quais podem ser as razões por trás disso?

Eu sei um pouco que não podemos fazer isso porque main é chamado pela biblioteca de tempo de execução e espera alguma sintaxe como int main() ou int main(int,char**) , então temos que nos ater a isso.

Então, minha pergunta é: por que main tem a assinatura de tipo que tem, e não diferente?

    
por JAVA 28.06.2013 / 22:37
fonte

3 respostas

83

O valor de retorno de main deve ser passado para o sistema operacional ( qualquer sistema operacional) de uma maneira única e consistente. A informação que o sistema operacional precisa saber é "o programa terminou com sucesso, ou houve algum erro?"

Se esta é uma string, a resposta se torna difícil em diferentes idiomas. As partes internas de uma cadeia Pascal (primeiro byte é comprimento) e uma cadeia FORTRAN (fixa, preenchida com algum valor) e uma cadeia C (terminada com nulo) são todas diferentes. Isso tornaria o retorno de um valor consistente para o sistema operacional desafiador. Assumindo que isso foi resolvido, o que você faria para responder à pergunta que o sistema operacional tinha sobre o programa? As comparações de strings são repletas de erros ("sucesso" x "Sucesso") e, embora o erro possa ser mais útil para um humano, é mais difícil para o sistema operacional ou para outro programa (shell) lidar. Também houve diferenças significativas até nas próprias strings - EBCDIC (com todas as suas páginas de código) vs. ASCII.

Flutuadores e duplas não fornecem nenhum valor adicional sobre o inteiro para a comunicação de dados de volta ao SO (e ao shell). Na maior parte, nenhuma dessas partes do computador lida com números de ponto flutuante. Os duplos também não são enumeráveis, tornando as comparações difíceis. Não sendo enumeráveis, eles relatam qual foi o erro (supondo que você escolheu um valor específico para o sucesso). Novamente, os pontos flutuantes não são consistentes - um float em uma máquina de 8 bits era diferente do float em uma máquina de 16 bits e 32 bits (e esses são apenas os 'normais' - mesmo dentro da IBM, o ponto flutuante não era padronizado entre máquinas pelo mesmo fabricante até os anos 80). E então você tem computadores decimais vs. binários. Valores de ponto flutuante não são consistentes e não fornecem dados significativos.

Isso realmente nos deixa com o byte e o inteiro como opções. A convenção que foi estabelecida foi '0' foi sucesso, e qualquer outra coisa foi um erro. Um inteiro dá mais espaço do que um byte para relatar o erro. Pode ser enumerado (retorno de 1 significa XYZ, retorno de 2 significa ABC, retorno de 3, significa DEF, etc.) ou usado como sinalizadores ( 0x0001 significa que isto falhou, 0x0002 significa que falhou, 0x0003 significa que isso e aquilo falharam). Limitar isso apenas a um byte poderia facilmente ficar sem sinalizadores (apenas 8), então a decisão era provavelmente usar um inteiro.

    
por 28.06.2013 / 23:00
fonte
27

Bem, isso poderia .

Por exemplo, no dialeto de C usado no sistema operacional Plano 9 main é normalmente declarado como uma função void , mas o status de saída é retornado ao ambiente de chamada passando um ponteiro de cadeia à função exits() . A string vazia denota sucesso, e qualquer string não vazia denota algum tipo de falha. Isso poderia ter sido implementado fazendo com que main retorne um resultado char* .

E certamente seria possível implementar um sistema com status de saída float ou double .

Então, por que int ? É apenas uma questão de convenção - e há um valor tremendo em ter sistemas operacionais e programas que correm sob eles obedecendo a uma convenção comum.

A convenção Unix é usar um código de status inteiro, com 0 denotando sucesso e falha de denotação diferente de zero (porque normalmente há apenas uma maneira de ter sucesso, mas várias maneiras de falhar). Não sei se essa convenção se originou com o Unix; Eu suspeito que veio de sistemas operacionais anteriores.

O ponto flutuante seria uma convenção mais difícil, porque (a) o suporte de ponto flutuante não é universal, (b) é mais difícil definir um mapeamento entre valores de ponto flutuante e condições de erro, (c) sistemas diferentes usam diferentes representações de ponto flutuante, e (d) imagine a diversão de rastrear um erro de arredondamento no status de saída do seu programa. Os inteiros, por outro lado, prestam-se muito bem na enumeração dos códigos de erro.

O plano 9, como mencionei, usa strings, mas isso impõe alguma complexidade para gerenciamento de memória, codificação de caracteres, etc. Foi, até onde eu sei, uma nova ideia quando o Plan 9 implementou, e não substituir a convenção generalizada existente.

(Incidentalmente, em C ++ main pode somente retornar int , e em C void main é permitido somente se o compilador suportar especificamente. Muitos compiladores não reclamam muito alto se você escreve void main , mas é apenas um pequeno exagero dizer que está errado .

    
por 29.06.2013 / 03:23
fonte
9

O valor retornado pelo método main é um "código de saída". É usado pelo aplicativo chamador (normalmente bash) para testar se o programa terminou conforme o esperado. Retornar um inteiro é a maneira mais fácil de fazê-lo no nível do sistema operacional. Duplo não faz sentido para o código de erro e uma String é difícil de manter no nível do sistema operacional (não há GC).

    
por 28.06.2013 / 23:02
fonte