Partilhar via


Protótipos de função

Uma declaração de função precede a definição de função e especifica o nome, o tipo de retorno, a classe de armazenamento e os outros atributos de uma função. Para ser um protótipo, a declaração de função também deve estabelecer os tipos e identificadores dos argumentos da função.

Sintaxe

declaration:
declaration-specifiers attribute-seqopt init-declarator-listopt ;

/* attribute-seqopt é específico da Microsoft */

declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt

init-declarator-list:
init-declarator
init-declarator-list , init-declarator

init-declarator:
declarator
declarator = initializer

declarator:
pointeropt direct-declarator

direct-declarator: /* Um declarador de função */
direct-declarator ( parameter-type-list ) /* Novo declarador de estilo */
direct-declarator ( identifier-listopt ) /* Declarador de estilo obsoleto */

O protótipo tem a mesma forma que a definição de função, exceto que é encerrado por um ponto e vírgula logo após o parêntese de fechamento e, portanto, não tem corpo. Em ambos os casos, o tipo de retorno deve concordar com o tipo de retorno especificado na definição de função.

Os protótipos de função têm os seguintes usos importantes:

  • Eles estabelecem o tipo de retorno para funções que retornam tipos diferentes de int. Embora as funções que retornem valores int não precisem de protótipos, os protótipos são recomendados.

  • Sem protótipos completos, as conversões padrão são feitas, mas nenhuma tentativa será feita para verificar o tipo ou o número de argumentos com o número de parâmetros.

  • Os protótipos são usados para inicializar ponteiros para as funções antes que essas funções sejam definidas.

  • A lista de parâmetros é usada para verificar quais argumentos na chamada de função correspondem aos parâmetros na definição de função.

O tipo convertido de cada parâmetro determina a interpretação dos argumentos que a chamada de função coloca na pilha. Uma incompatibilidade entre um argumento e um parâmetro pode fazer com que os argumentos na pilha sejam interpretados incorretamente. Por exemplo, em um computador de 16 bits, se um ponteiro de 16 bits for passado como um argumento e então declarado como um parâmetro long, os primeiros 32 bits da pilha serão interpretados como um parâmetro long. Esse erro cria problemas não apenas com o parâmetro long, mas com todos os parâmetros subsequentes. Você pode detectar erros desse tipo declarando protótipos de função completos para todas as funções.

Um protótipo estabelece os atributos de uma função. Em seguida, as chamadas de função que precedem a definição da função (ou que ocorrem em outros arquivos de origem), podem ser verificadas quanto a incompatibilidades de tipo de argumento e de retorno. Por exemplo, se você especificar o especificador de classe de armazenamento static em um protótipo, também deve especificar a classe de armazenamento static na definição de função.

As declarações completas de parâmetro (int a) podem ser combinadas com os declaradores abstratos (int) na mesma instrução. Por exemplo, a declaração a seguir é aceitável:

int add( int a, int );

O protótipo pode incluir o tipo e um identificador para cada expressão que seja passada como um argumento. Porém, tais identificadores permanecem no escopo apenas até o final da declaração. O protótipo também pode refletir o fato de que o número de argumentos é variável ou que nenhum argumento é passado. Sem essa lista, as incompatibilidades podem não ser reveladas, portanto o compilador não poderá gerar mensagens de diagnóstico relacionadas a elas. Para obter mais informações sobre verificação de tipo, consulte Argumentos.

O escopo de protótipo no compilador do Microsoft C agora está em conformidade com ANSI ao compilar com a opção /Za do compilador. Se você declarar uma marca struct ou union dentro de um protótipo, a marca será inserida nesse escopo em vez do escopo global. Por exemplo, ao compilar com /Za, para estar em conformidade com ANSI, você nunca poderá chamar essa função sem receber um erro de incompatibilidade:

void func1( struct S * );

Para corrigir seu código, defina ou declare struct ou union no escopo global antes de protótipo da função:

struct S;
void func1( struct S * );

Em /Ze, a marca ainda é inserida no escopo global.

Confira também

Funções