Pergunta

O que é útil sobre isso C Sintaxe - Usando declarações de função do estilo 'K&R'?

int func (p, p2)
    void* p;
    int  p2;
{
    return 0;
}

Consegui escrever isso no Visual Studios 2010beta

// yes, the arguments are flipped
void f()
{
    void* v = 0;
    func(5, v);
}

Não entendo. Qual é o objetivo desta sintaxe? Eu consigo escrever:

int func (p, p2)
    int  p2;
{
    return 0;
}
// and write
int func (p, p2)
{
    return 0;
}

A única coisa que parece especificar é quantos parâmetros ele usa e o tipo de retorno. Eu acho que parâmetros sem tipos são bem legais, mas por que permitir e o int paranName Após o declarador da função? É estranho.

Também isso ainda é padrão C?

Foi útil?

Solução

A pergunta que você está fazendo são realmente duas perguntas, não uma. A maioria das respostas até agora tentou cobrir a coisa toda com um cobertor genérico "This Is K&R Style", enquanto na verdade apenas uma pequena parte dela tem algo a ver com o que é conhecido como estilo K&R (a menos que você veja o idioma C inteiro como "K&R-Style" de uma maneira ou de outra :)

A primeira parte é a sintaxe estranha usada em função definição

int func(p, p2)
void *p;
int  p2; /* <- optional in C89/90, but not in C99 */
{
  return 0;
}

Este é na verdade uma definição de função no estilo K & R. Outra resposta cobriu isso muito bem. E não há muito, na verdade. A sintaxe é descontinuada, mas ainda é totalmente suportada mesmo em C99 (exceto "nenhuma regra implícita int" em C99, o que significa que em C99 você não pode omitir a declaração de p2).

A segunda parte tem pouco a ver com o estilo K & R. Refiro -me ao fato de que a função pode ser chamada com argumentos "trocados", ou seja, nenhuma verificação do tipo de parâmetro ocorre nessa chamada. Isso tem muito pouco a ver com a definição no estilo K & R em si, mas tem tudo a ver com sua função sem protótipo. Veja, em C quando você declara uma função como esta

int foo();

na verdade declara uma função foo isso leva um número não especificado de parâmetros do tipo desconhecido. Você pode chamá -lo como

foo(2, 3);

e como

j = foo(p, -3, "hello world");

Ans So So (você entendeu);

Somente a chamada com argumentos adequados "funcionará" (o que significa que os outros produzem comportamento indefinido), mas depende de você garantir sua correção. O compilador não é necessário para diagnosticar os incorretos, mesmo que de alguma forma conheça magicamente os tipos de parâmetros corretos e seu número total.

Na verdade, esse comportamento é um característica da linguagem C. Um perigoso, mas um recurso, no entanto. Permite que você faça algo assim

void foo(int i);
void bar(char *a, double b);
void baz(void);

int main()
{
  void (*fn[])() = { foo, bar, baz };
  fn[0](5);
  fn[1]("abc", 1.0);
  fn[2]();
}

ou seja, misture diferentes tipos de funções em uma matriz "polimórfica" sem timpastos (os tipos de funções variádicas não podem ser usadas aqui). Novamente, os perigos inerentes a essa técnica são bastante óbvios (não me lembro de ter usado, mas posso imaginar onde pode ser útil), mas isso é C afinal.

Finalmente, a parte que vincula a segunda parte da resposta ao primeiro. Quando você faz uma definição de função no estilo K&R, ela não apresenta um protótipo para a função. No que diz respeito ao tipo de função, seu func Definição declara func Como

int func();

ou seja, nem os tipos nem o número total de parâmetros são declarados. Na sua postagem original, você diz "... parece especificar é quantos parâmetros ele usa ...". Formalmente falando, não! Após o seu estilo K & R de dois parâmetros func Definição que você ainda pode ligar func Como

func(1, 2, 3, 4, "Hi!");

E não haverá nenhuma violação de restrição. (Normalmente, um compilador de qualidade lhe dará um aviso).

Além disso, um fato às vezes esquecido é que

int f()
{
  return 0;
}

também é uma definição de função no estilo K & R que não introduz um protótipo. Para torná -lo "moderno", você teria que colocar um explícito void na lista de parâmetros

int f(void)
{
  return 0;
}

Finalmente, ao contrário de uma crença popular, as definições de função no estilo K & R e as declarações de função não prototipadas são totalmente suportadas no C99. O primeiro foi depreciado desde C89/90, se bem me lembro. C99 exige que a função seja declarada antes do primeiro uso, mas a declaração não é necessária para ser um protótipo. Aparentemente, a confusão decorre da confusão terminológica popular: muitas pessoas chamam qualquer declaração de função de "um protótipo", enquanto de fato "a declaração da função" não é a mesma coisa que "protótipo".

Outras dicas

Esta é uma sintaxe K&R C bastante antiga (pré-datas ANSI/ISO C). Atualmente, você não deve mais usá -lo (como já notou sua grande desvantagem: o compilador não verificará os tipos de argumentos para você). O tipo de argumento realmente padroniza para int no seu exemplo.

Na época, essa sintaxe era usada, às vezes encontrava funções como

foo(p, q) 
{
    return q + p;
}

o que era realmente uma definição válida, como os tipos para foo, p, e q padrão para int.

Esta é simplesmente uma sintaxe antiga, que antecede a sintaxe "ANSI C" com a qual você pode estar mais familiarizado. É chamado "K&R C", normalmente.

Os compiladores suportam que ele seja completo e para poder lidar com as bases de código antigas, é claro.

Esta é a sintaxe K&R original antes de C ser padronizada em 1989. C89 Introduziu protótipos de função, emprestados de C ++, e depreciou a sintaxe de K&R. Não há razão para usá -lo (e muitas razões para não) no novo código.

Essa é uma relíquia de quando C não tinha protótipos para funções. Naquela época, (eu acho) as funções foram assumidas para retornar int e todos os seus argumentos foram assumidos como serem int. Não houve verificação feita nos parâmetros da função.

Você é muito melhor usando protótipos de função no idioma C atual.
E você devo Use -os em C99 (C89 ainda aceita a sintaxe antiga).

E C99 exige que as funções sejam declaradas (possivelmente sem um protótipo). Se você está escrevendo uma nova função do zero, precisará fornecer uma declaração ... faça um protótipo também: você não perde nada e obtém verificação extra do compilador.

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