Składnia funkcji C, typy parametrów deklarowane po liście parametrów

Jestem stosunkowo nowy w C. natknąłem się na formę składni funkcji, jakiej nigdy wcześniej nie widziałem, gdzie typy parametrów są definiowane po tej liście parametrów. Może mi ktoś wyjaśnić czym różni się od typowej składni funkcji C?

Przykład:

int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
Author: Jonathan Leffler, 2009-10-18

6 answers

To stara składnia list parametrów, która jest nadal obsługiwana. W K & R C można by też pominąć deklaracje typu i domyślne to int. tj.

main(argc, argv)
char *argv[];
{
    return 0;
}

Będzie tą samą funkcją.

 58
Author: Ferruccio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-18 16:50:30

Interesująca jest również różnica w konwencji wywołania funkcji Z, oraz funkcji bez prototypu. Rozważmy definicję starego stylu:

void f(a)
 float a; {
 /* ... */
}

W tym przypadku konwencja wywołania polega na tym, że wszystkie argumenty są promowane przed przekazaniem ich do funkcji. Jeśli więc f otrzyma double, ale parametr ma typ float (co jest doskonale poprawne), kompilator musi emitować kod, który konwertuje double na float przed wykonaniem funkcji.

Jeśli dołączenie prototypu, kompilator nie robi już takich automatycznych promocji i wszelkie przekazywane dane są konwertowane do typów parametrów prototypu, jak gdyby przez przypisanie. Tak więc następujące rzeczy nie są legalne i skutkują niezdefiniowanym zachowaniem:

void f(float a);
void f(a)
  float a; {

}

W tym przypadku definicja funkcji przekształciłaby Podany parametr z double (promowana forma) na float, ponieważ definicja jest w starym stylu. Ale parametr został przedstawiony jako float, ponieważ funkcja ma prototyp. Twoje opcje rozwiązania sprzeczności są następujące:

// option 1
void f(double a);
void f(a)
  float a; {

}

// option 2
// this declaration can be put in a header, but is redundant in this case, 
// since the definition exposes a prototype already if both appear in a 
// translation unit prior to the call. 
void f(float a); 

void f(float a) {

}

Opcja 2 powinna być preferowana, jeśli masz wybór, ponieważ usuwa starą definicję stylu z przodu. Jeśli takie sprzeczne typy funkcji dla funkcji pojawiają się w tej samej jednostce translacyjnej, kompilator zazwyczaj ci o tym powie (ale nie jest to wymagane). Jeśli takie sprzeczności pojawią się w wielu jednostkach tłumaczeniowych, błąd prawdopodobnie pozostanie niezauważony i może spowodować trudne do przewidzenia błędy. On najlepiej unikać tych starych definicji stylu.

 25
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-10 17:21:01

Jest to tzw. deklaracja K&R style lub old-style.

Zauważ, że deklaracja ta jest znacząco odmienna od współczesnej deklaracji. Deklaracja K & R nie wprowadza prototypu dla funkcji, co oznacza, że nie wystawia typów parametrów na Zewnętrzny kod.

 10
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-06 16:44:15

Chociaż stara składnia definicji funkcji nadal działa (z ostrzeżeniami, jeśli zapytasz kompilatora), używanie ich nie zapewnia prototypów funkcji.
Bez prototypów funkcji kompilator nie sprawdzi, czy funkcje są wywoływane poprawnie.

#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }

int bar(x)
double x;
{ return printf("%f\n", x); }

int main(void)
{
    foo(42); /* ok */
    bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
    return 0;
}

Gdy program jest uruchomiony, wyjście na moim komputerze jest

$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
 4
Author: pmg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-18 17:09:24

Nie ma różnicy, po prostu jest to stara składnia deklaracji funkcji w C -- została użyta przed ANSI. Nigdy nie pisz takiego kodu, chyba że planujesz dać go znajomym z lat 80. . Ponadto, nigdy nie zależą od niejawnych założeń typu (Jak sugeruje inna odpowiedź)

 3
Author: aviraldg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-18 17:03:42

To taka sama, ale stara moda. Pewnie zauważyłeś, że to jakiś stary, legacy kod.

 1
Author: eyalm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-18 16:55:28