Pergunta

transcrição da sessão:

>type lookma.c
int main() {
  printf("%s", "no stdio.h");
}

>cl lookma.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

lookma.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:lookma.exe
lookma.obj

>lookma
no stdio.h
Foi útil?

Solução

No modo de cumprimento rigoroso (que significa "em teoria"), você invoca o comportamento indefinido (o que é ruim) quando você chamar uma função que leva um número variável de argumentos sem uma declaração protótipo da função no escopo. Isso significa que o compilador é permitido fazer qualquer coisa que quiser com um programa que usa printf() sem o protótipo de #include <stdio.h> ou uma declaração equivalente. "Qualquer coisa que ele gosta" inclui trabalhar corretamente como uma das opções; que parece ser a opção escolhida pelo seu exemplo.

Na prática, o código irá funcionar bem com a maioria dos compiladores práticos, mesmo sem a declaração formal da função printf().

Como foi apontado por qrdl, a função foi encontrado porque as ligações do compilador C com a biblioteca C.

Note que o comentário de Chris Young sobre C99 e 'int implícita' é preciso, mas a regra sobre os argumentos de funções variáveis ??devem ter um protótipo no escopo "se aplica tanto C89 e C99. A maioria dos compiladores não funcionam no modo de compatibilidade C99 estrita por padrão porque não há muito código que não compilar assim.

Chris Young comentou:

Para esclarecer, meu comentário foi em C99 remover declarações implícitas. Ao dizer "int implícita", eu acho que você está se referindo ao recurso de C89 de permitir que declarações como foo (void); para foo int média (void) ;, algo C99 também removidos.

Chris é, naturalmente, correta. Havia dois 'declaração implícita' apresenta removido do padrão C99. O prefácio para as listas padrão los como:

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

Eu não estava pensando (e, portanto, não escrever) com clareza suficiente. No entanto, tanto C89 e C99 exigem um protótipo no escopo para funções que recebem um número variável de argumentos.

Para ilustrar:

extern int pqr();
int main(void)
{
    int i = pqr(1, 3);
    return i;
}

Sem a primeira linha, este é um fragmento C89 correto com uma declaração implícita do pqr() função como uma função que retorna um número inteiro (com argumentos não especificadas). Se a primeira linha é substituída por extern pqr();, então este é um fragmento C89 correto com uma declaração explícita de pqr() como uma função que retorna uma inteiros (com os argumentos não especificados), mas o tipo de retorno é 'int implícito'. Como escrito, a função é explicitamente declarado e tem um tipo de int retorno explícita - mas ainda tem os argumentos não especificados. Eu acredito que é C99 válida - embora não totalmente desejável. Certamente, GCC (3.4.4) aceita-lo com -std=c99 -pedantic das opções". Idealmente, a declaração de função deve incluir o protótipo completo. (E, se pqr() foram definidos com reticências, esse protótipo seria necessário em teoria !)

Outras dicas

Você tinha originalmente marcado este C ++, mas parece ser um programa C. C irá fornecer automaticamente uma declaração implícita de uma função se não houver nenhum protótipo no escopo (como devido à omissão de #include ). A declaração implícita seria:

int printf();

O que significa que printf é uma função que retorna um inteiro e pode assumir qualquer número de argumentos. Este protótipo passou a trabalhar para a sua chamada. Você deve #include

Finalmente, devo acrescentar que o padrão C corrente (ISO / IEC 9899: 1999 ou coloquialmente "C99") faz não permitem declarações implícitas, e este programa não iria se conformar. declarações implícitas foram removidos. Eu acredito que o seu compilador não suporta C99. C ++ também requer protótipos corretos e não faz declarações implícitas.

printf() está localizado na biblioteca C padrão e vinculador sempre liga biblioteca padrão para o executável, portanto, quaisquer funções padrão será encontrado e não haverá problemas de ligação.

A não incluem os resultados de cabeçalho apropriadas em usar a função que não foi um protótipo que pode levar a problemas, como compilador C assume essa função, sem protótipos retornos int e leva um número variável de argumentos. Então, sempre incluem cabeçalho - é a sua vedação de segurança

.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top