Acabei de encontrar o código C de alguém que estou confuso sobre o motivo de ele estar compilando. Existem dois pontos que não entendo.
Primeiro, o protótipo da função não possui parâmetros em comparação com a definição real da função. Segundo, o parâmetro na definição da função não tem um tipo.
#include <stdio.h>
int func();
int func(param)
{
return param;
}
int main()
{
int bla = func(10);
printf("%d", bla);
}
Por que isso funciona? Eu testei em alguns compiladores e funciona bem.
c
parameters
function-prototypes
function-parameter
AdmiralJonB
fonte
fonte
-Wstrict-prototypes
tanto para a declaraçãoint func()
comoint main()
: xc: 3: warning: function: não é um protótipo. Você deve declararmain()
comomain(void)
bem.int func();
é compatível comint func(arglist) { ... }
.int main(void)
.Respostas:
Todas as outras respostas estão corretas, mas apenas para conclusão
E novamente por uma questão de completude. Na especificação C11 6: 11: 6 (página: 179)
fonte
Em C
func()
significa que você pode passar qualquer número de argumentos. Se você não quer argumentos, deve declarar comofunc(void)
. O tipo que você está passando para a sua função, se não especificado, é padronizado comoint
.fonte
func(42,0x42);
(onde todas as chamadas devem usar o formulário de dois argumentos).unsigned
é apenas outro nome para o mesmo tipo queunsigned int
.int func();
é uma declaração de função obsoleta dos dias em que não havia um padrão C, ou seja, os dias da K&R C (antes de 1989, ano em que o primeiro padrão "ANSI C" foi publicado).Lembre-se de que não havia protótipos no K&R C e a palavra-chave
void
ainda não foi inventada. Tudo o que você pôde fazer foi informar o compilador sobre o tipo de retorno de uma função. A lista de parâmetros vazia no K&R C significa "um número não especificado, mas fixo" de argumentos. Significa que você deve chamar a função com o fixo mesmo número de argumentos de cada vez (ao contrário de um variádica função comoprintf
, onde o número e tipo pode variar para cada chamada).Muitos compiladores diagnosticam essa construção; em particular
gcc -Wstrict-prototypes
, dirá que "a declaração de função não é um protótipo", o que é óbvio, porque parece um protótipo (especialmente se você está envenenado por C ++!), mas não é. É uma declaração de tipo de retorno K&R C de estilo antigo.Regra geral: nunca deixe uma declaração vazia da lista de parâmetros em branco, use
int func(void)
para ser específico. Isso transforma a declaração de tipo de retorno K&R em um protótipo C89 adequado. Compiladores estão felizes, desenvolvedores estão felizes, verificadores estáticos estão felizes. Aqueles enganados por ^ W ^ Wfond de C ++ podem se encolher, no entanto, porque precisam digitar caracteres extras quando tentam exercitar suas habilidades em idiomas estrangeiros :-)fonte
int
.Eu consideraria qualquer compilação que passa isso com falta de nível de aviso / erro configurado, porém, não há sentido em permitir isso para o código real.
fonte
É declaração e definição de função no estilo K&R . Do padrão C99 (ISO / IEC 9899: TC3)
Seção 6.7.5.3 Declaradores de função (incluindo protótipos)
Seção 6.11.6 Declaradores de função
Seção 6.11.7 Definições de funções
Que o velho estilo significa K & R estilo
Exemplo:
Declaração:
int old_style();
Definição:
fonte
C assume
int
se nenhum tipo é fornecido no tipo de retorno da função e na lista de parâmetros . Somente para esta regra é possível seguir coisas estranhas.Uma definição de função se parece com isso.
Se é um protótipo que você escreve
No protótipo, você pode especificar apenas o tipo de parâmetros. O nome dos parâmetros não é obrigatório. assim
Além disso, se você não especificar o tipo de parâmetro, mas o nome
int
será assumido como tipo.Se você for mais longe, o seguinte também funciona.
O compilador assume
int func()
quando você escrevefunc()
. Mas não coloquefunc()
dentro de um corpo funcional. Isso será uma chamada de funçãofonte
int func()
não é uma forma implícita deint func(int)
.Conforme afirmado @Krishnabhadra, todas as respostas anteriores de outros usuários têm uma interpretação correta e eu só quero fazer uma análise mais detalhada de alguns pontos.
No Old-C, como no ANSI-C, o " parâmetro formal sem tipo " leva em consideração a dimensão do seu registro de trabalho ou a capacidade de profundidade das instruções (registros de sombra ou ciclo cumulativo de instruções), em uma MPU de 8 bits, será um int16, em 16 bits. MPU e assim será um int16 e assim por diante, no caso de arquiteturas de 64 bits podem optar por compilar opções como: -m32.
Embora pareça uma implementação mais simples em alto nível, para passar vários parâmetros, o trabalho do programador na etapa do tipo de dados de controle de dimensão torna-se mais exigente.
Em outros casos, para algumas arquiteturas de microprocessadores, os compiladores ANSI customizados utilizaram alguns desses recursos antigos para otimizar o uso do código, forçando a localização desses "parâmetros formais não digitados" para trabalhar dentro ou fora do registro de trabalho, hoje você obtém quase o mesmo com o uso de "volátil" e "registrar".
Mas deve-se notar que os compiladores mais modernos não fazem distinção entre os dois tipos de declaração de parâmetros.
Exemplos de uma compilação com o gcc no linux:
De qualquer forma, a declaração do protótipo localmente não é útil, porque não há chamada sem parâmetros, a referência a este protótipo será negligente. Se você usar o sistema com "parâmetro formal sem tipo", para uma chamada externa, continue gerando um tipo de dados declarativo de protótipo.
Como isso:
fonte
int
, que geralmente é do tamanho do registro de trabalho ou de 16 bits, o que for menor.int
tipo que não fosse capaz de manter todos os valores no intervalo - 32767 a +32767 (a nota -32768 não é necessária) e também é capaz de manter todos oschar
valores (o que significa que sechar
for de 16 bits, ele deve ser assinado ouint
deve ser maior).Com relação ao tipo de parâmetro, já existem respostas corretas aqui, mas se você quiser ouvi-lo do compilador, tente adicionar alguns sinalizadores (os sinalizadores são quase sempre uma boa ideia).
compilando seu programa usando
gcc foo.c -Wextra
eu recebo:estranhamente
-Wextra
não pega isso porclang
(não reconhece-Wmissing-parameter-type
por algum motivo, talvez pelos históricos mencionados acima), mas-pedantic
faz:E, para a questão do protótipo, como dito novamente acima,
int func()
refere-se a parâmetros arbitrários, a menos que você o defina de maneira exclusiva, oint func(void)
que forneceria os erros conforme o esperado:ou
clang
como:fonte
Se a declaração da função não tiver parâmetros, isto é, vazia, estará recebendo um número não especificado de argumentos. Se você quiser fazê-lo, não use argumentos, altere-o para:
fonte
É por isso que normalmente aconselho as pessoas a compilarem seu código:
Essas bandeiras reforçam algumas coisas:
Esses sinalizadores também são usados por padrão em muitos projetos de código aberto. Por exemplo, o FreeBSD tem esses sinalizadores ativados ao criar com WARNS = 6 em seu Makefile.
fonte