São protótipos necessários para todas as funções em C89, C90 ou C99?

StackOverflow https://stackoverflow.com/questions/434763

  •  10-07-2019
  •  | 
  •  

Pergunta

Para ser verdadeiramente compatível com padrões, devem todas as funções em C (exceto principal) tem um protótipo, mesmo se eles são usados ??somente após a sua definição na mesma unidade de tradução?

Foi útil?

Solução

Depende do que você quer dizer com 'compatível verdadeiramente padrões'. No entanto, a resposta curta é "é uma boa idéia para garantir que todas as funções têm um protótipo no escopo antes de ser usado".

A Notas resposta mais qualificados que se a função aceita argumentos variáveis ??(nomeadamente a família printf() de funções), então um protótipo deve estar no escopo para ser compatível rigorosamente as normas. Isto é verdade para C89 (de ANSI) e C90 (de ISO; o mesmo como C89, excepto para a numeração secção). Diferente de 'varargs' funções, porém, funções que retornam um int não têm de ser declaradas, e as funções que o retorno algo diferente de um int precisa de uma declaração que mostra o tipo de retorno, mas não precisam o protótipo para a lista de argumentos.

Note, no entanto, que se a função leva argumentos que estão sujeitas a 'promoções normais' na ausência de protótipos (por exemplo, uma função que leva um char ou short - ambos os quais são convertidos para int; mais a sério, talvez, uma função que leva um float em vez de um double), então é necessário um protótipo. O padrão foi relaxado sobre esta para permitir que o código C velho para compilar sob compiladores conformant padrão; código antigo não foi escrito para se preocupar com a garantia de que as funções foram declaradas antes do uso -. e, por definição, código antigo não utilizar protótipos, uma vez que não se tornou disponível em C até que houvesse um padrão

C99 Não permite a 'int implícita' ... isso significa que ambos os casos esquisitos como 'static a;' (um int por padrão) e também declarações de função implícitas. Estes são mencionados (juntamente com cerca de 50 outras alterações importantes) no prefácio com a norma ISO / IEC 9899: 1999, o que compara esse padrão com as versões anteriores:

  • remover implícita int
    ...
  • remover declaração da função implícita

Na ISO / IEC 9899: 1990, §6.3.2.2 chamadas Função declarou:

Se a expressão que precede a lista de argumentos entre parênteses em uma chamada de função consiste unicamente de um identificador, e se a declaração não é visível para este identificador, o identificador é implicitamente declarou exatamente como se, no bloco mais interno que contém a chamada de função, a declaração:

extern int identifier();

apareceu. 38

38 Ou seja, um identificador com escopo de bloco declarou ter ligação externa com função de tipo sem informações de parâmetro e retornar um int. Se na verdade não é definido como tendo função de tipo “ retornando int “, o comportamento é indefinido.

Este parágrafo está faltando no padrão de 1999. Eu tenho (ainda) não acompanhou a mudança de palavreado que permite static a; em C90 desautorizando-lo (o que exige static int a;) em C99.

Note que, se a função é estático, ele pode ser definido antes de ser usado, e não precisa ser precedido por uma declaração. GCC podem ser persuadidos a witter se uma função não-estático é definido sem uma declaração precedente (-Wmissing-prototypes).

Outras dicas

A protótipo é uma declaração de função que especifica os tipos de parâmetros da função.

Pré-ANSI C (a língua descrito por 1978 primeira edição do Kernighan & Ritchie, "The C Programming Language") não tem protótipos; que não era possível para uma declaração de função para descrever o número ou tipos de parâmetros. Foi até o chamador para passar o número correto e tipo de argumentos.

ANSI C introduzido "protótipos", declarações que especificam os tipos dos parâmetros (um recurso emprestado do C ++ no início).

A partir de C89 / C90 (os padrões ANSI e ISO descrever o mesmo idioma), é legal para chamar uma função sem declaração visível; uma declaração implícita é fornecida. Se a declaração implícita é incompatível com a definição real (digamos, chamando sqrt("foo"), então o comportamento é indefinido. Nem esta declaração implícita nem uma declaração não-protótipo pode ser compatível com uma função de aridade variável, portanto, qualquer chamada para uma função aridade variável (como printf ou scanf) deve ter um protótipo visível.

C99 caiu declarações implícitas. Qualquer chamada para uma função sem uma declaração visível é uma violação de restrição, o que requer um compilador de diagnóstico. Mas essa declaração ainda não é obrigado a ser um protótipo; ele pode ser uma declaração de estilo antigo que não especifica o parâmetro tipos.

C11 não fez alterações significativas nesta área.

Assim, mesmo a partir do Standard 2011 ISO C, de estilo antigo declarações e definições de função (que foram "obsoleta" desde 1989) são ainda permitidos em conformidade código.

Para todas as versões do C de volta a 1989 vai, como uma questão de estilo, há muito pouca razão para não usar protótipos para todas as funções. declarações e definições de estilo antigo são mantidos apenas para evitar quebrar o código antigo.

Não, funções nem sempre precisa de um protótipo. A única exigência é que uma função ser "declarado" antes de usá-lo. Há duas maneiras de declarar uma função: (. "Definição" chamado a) para escrever um protótipo, ou para escrever a própria função Uma definição é sempre uma declaração, mas nem todas as declarações são definições

.

Sim, cada função deve ter um protótipo, mas que protótipo podem aparecer em uma declaração separada ou como parte da definição da função. As definições de função escritos em C89 e até naturalmente têm protótipos, mas se você escrever coisas em K clássico e estilo R, assim:

main (argc, argv)

  int argc;
  char **argv;

{
  ...
}

, em seguida, a definição da função não tem protótipo. Se você escrever ANSI C estilo (C89), assim:

main (int argc, char **argv) { ... }

então a definição de função tem um protótipo.

Uma boa dica quando escrever novas funções é escrevê-los de cabeça para baixo com principal em baixo assim quando você mudar de idéia sobre args da função ou tipo de retorno você não tem que corrigir o protótipo também. fixação constantemente protótipos, e lidar com todos os avisos do compilador quando eles estão fora da data fica muito tedioso.

Depois de ter suas funções de trabalho sem problemas juntos mover o código a um módulo bem-nomeados e colocar os protótipos em um arquivo .h de mesmo nome. Ele economiza tempo sério. A maior ajuda produtividade que eu encontrei em 5 anos.

Para o melhor de meu conhecimento (em ANSI C89 / ISO C90), não. Estou inseguro sobre C99; no entanto, eu esperaria o mesmo.

Nota pessoal: I apenas protótipos de função de gravação quando ...

  1. Eu preciso (quando A () chama B () e B () chama A ()), ou
  2. Estou a exportar a função; caso contrário, ele sente supérflua.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top