Pergunta

Configuração

Eu tenho algumas perguntas sobre as promoções de argumento padrão ao chamar uma função em C. de Aqui seção 6.5.2.2 "chamadas de função" Os parágrafos 6, 7 e 8 do padrão C99 (pdf) (grifos e dividido em listas para facilitar a leitura):

Parágrafo 6

  1. Se a expressão que denota a função chamada tem um tipo que não inclui um protótipo , as promoções inteiros são executadas em cada argumento e argumentos que têm tipo float são promovidos a double. Estes são chamados os promoções de argumento padrão .
  2. Se o número de argumentos não é igual o número de parâmetros, o comportamento é indefinido.
  3. Se a função é definida com um tipo que inclui um protótipo , e quer as extremidades protótipo com reticências (, ...) ou os tipos dos argumentos depois promoção não são compatíveis com os tipos de parâmetros, o comportamento é indefinido.
  4. Se a função é definida com um tipo que não inclui um protótipo , e os tipos dos argumentos após a promoção não são compatíveis com os dos parâmetros após a promoção, o comportamento é indefinido, excepto para os seguintes casos:
    • um tipo promovido é um tipo inteiro assinado, o outro tipo promovido é o tipo inteiro sem sinal correspondente, eo valor é representável em ambos os tipos;
    • ambos os tipos são ponteiros para as versões qualificados ou não qualificados de um tipo de caráter ou void.

n.º 7

  1. Se a expressão que denota a função chamada tem um tipo que não inclui um protótipo , os argumentos são convertidos implicitamente, como se pela atribuição, aos tipos dos parâmetros correspondentes, tendo o tipo de cada parâmetro a ser a versão incondicional do seu tipo declarado.
  2. A notação reticências em um declarator protótipo função faz com que a conversão tipo de argumento para parar após o último parâmetro declarado. As promoções de argumento padrão são executadas em argumentos finais.

N.º 8

  1. Não há outras conversões são executadas implicitamente; em particular, o número e tipos de argumentos não são comparados com os dos parâmetros em uma definição de função que não inclui uma função protótipo declarator .

O que eu sei

  • O promoções de argumento padrão são char e short para int / unsigned int e float para double
  • Os argumentos opcionais para funções variádicos (como printf) estão sujeitos às promoções de argumento padrão

Para o registro, o meu entendimento de um função protótipo é o seguinte:

void func(int a, char b, float c);  // Function prototype
void func(int a, char b, float c) { /* ... */ }  // Function definition

Pergunta

Eu estou tendo um momento muito difícil groking tudo isso. Aqui estão algumas perguntas que eu tenho:

  • Do protótipo e comportamento funções não prototipados realmente diferem tanto, como no que diz respeito a promoções padrão e conversões implícitas?
  • Quando promoções de argumento padrão ocorre? É sempre? Ou é apenas em casos especiais (como com funções variádicos)? Será que depende se uma função é um protótipo?

Foi útil?

Solução

resposta-os de Upvoted AProgrammer são os bens reais.

Para aqueles de vocês que estão se perguntando por as coisas são assim: na idade das trevas antes de 1988, não havia tal coisa como um protótipo de função no clássico "K & R" C, e o argumento padrão promoções foram instituídos porque (a) não eram essencialmente "livre", uma vez que não mais custa para colocar um byte de um registo do que colocar uma palavra em um registro, e (b) para reduzir potenciais erros na passagem de parâmetros. Essa segunda razão nunca completamente cortá-lo, razão pela qual a introdução de protótipos de função em ANSI C foi a única mudança mais importante de sempre na linguagem C.

Quanto ao momento promoções padrão chutar em: promoções de argumento padrão são usados ??exatamente quando o tipo esperado do argumento é desconhecido , o que quer dizer quando não há protótipo ou quando o argumento é variádica.

Outras dicas

  • (não variádica) parâmetros de funções com um protótipo são convertidos para o tipo correspondente, que pode ser char, curto, flutuador.

  • Parâmetros para funções sem protótipo e parâmetros variádicos estão sujeitos a promoções de argumento padrão.

Se você definir uma função com um protótipo e usá-lo sem o protótipo ou vice versa e tem parâmetros do tipo char, short ou float, você provavelmente vai ter um problema em tempo de execução. Você vai ter o mesmo tipo de problemas com funções variádicos se o tipo promovido não correspondem ao que é usado ao ler a lista de argumentos.

Exemplo 1:. Problema quando definindo uma função com um protótipo e utilizá-lo sem

definition.c

void f(char c)
{
   printf("%c", c);
}

use.c

void f();

int main()
{
   f('x');
}

pode falhar porque um int será passado ea função espera um char.

Exemplo 2:. Problema quando definindo uma função sem um protótipo e usá-lo com um

definition.c

void f(c)
   char c;
{
   printf("%c", c);
}

(Este é tipo de definição é muito antigo)

use.c

void f(char c);

int main()
{
   f('x');
}

pode falhar porque um int é esperado, mas um char será passado.

Nota: você vai observar que todas as funções da biblioteca padrão ter tipos que resultam de promoções padrão. Então, eles não causa problema durante a transição quando protótipos foram adicionados.

Seu confusão deriva de uma muito ligeira incompreensão da terminologia - ambas as declarações e definições podem incluir protótipos (ou não):

void func(int a, char b, float c);

Isso é uma função declaração , que inclui um protótipo.

void func(int a, char b, float c) { /* ... */ }

Isso é uma função definição , que inclui um protótipo.

"protótipo" e "não-protótipo" são apenas atributos de uma função tipo , e ambas as declarações e definições introduzir o tipo da função.

Então você pode ter uma declaração sem um protótipo:

void func();

ou você pode ter uma definição sem um protótipo (K & R estilo C):

void func(a, b, c)
    int a;
    char b;
    float c;
{ /* ... */ }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top