Alternative (K&R) C-Syntax für Funktionsdeklaration im Vergleich zu Prototypen

Lesezeit: 6 Minuten

Was ist daran nützlich C Syntax — Verwendung von Funktionsdeklarationen im K&R-Stil?

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

Ich konnte dies in Visual Studios 2010beta schreiben

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

Ich verstehe nicht. Was ist der Sinn dieser Syntax? Ich kann schreiben:

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

Das einzige, was es anzugeben scheint, ist die Anzahl der verwendeten Parameter und der Rückgabetyp. Ich denke, Parameter ohne Typen sind irgendwie cool, aber warum sollten Sie das zulassen und die int paranName nach dem Funktionsdeklarator? Es ist komisch.

Ist das auch noch Standard C?

  • Es ist ein älterer Stil von Funktionsdeklarationen. Bitte sehen Sie sich diesen Link an. https://stackoverflow.com/questions/22500/what-are-the-major-differences-between-ansi-c-and-kr-c Linktext

    – Leonidas Tsampros

    27. Oktober 2009 um 13:04 Uhr

AnT steht mit Russlands Benutzer-Avatar
AnT steht zu Russland

Die Frage, die Sie stellen, sind eigentlich zwei Fragen, nicht eine. Die meisten Antworten haben bisher versucht, das Ganze mit einer allgemeinen pauschalen Antwort “Das ist K&R-Stil” zu überdecken, während tatsächlich nur ein kleiner Teil davon etwas mit dem zu tun hat, was als K&R-Stil bekannt ist (es sei denn, Sie sehen die gesamte C-Sprache als “K&R-Stil” auf die eine oder andere Weise 🙂

Der erste Teil ist die seltsame Syntax, die in function verwendet wird Definition

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

Dies ist eigentlich eine Funktionsdefinition im K&R-Stil. Andere Antworten haben dies ziemlich gut abgedeckt. Und eigentlich ist nicht viel dran. Die Syntax ist veraltet, wird aber auch in C99 noch vollständig unterstützt (mit Ausnahme der Regel “no implicit int” in C99, was bedeutet, dass Sie in C99 die Deklaration von nicht weglassen können p2).

Der zweite Teil hat wenig mit K&R-Stil zu tun. Ich verweise darauf, dass die Funktion mit “ausgetauschten” Argumenten aufgerufen werden kann, dh bei einem solchen Aufruf findet keine Parametertypprüfung statt. Das hat sehr wenig mit der Definition im K&R-Stil an sich zu tun, aber es hat alles damit zu tun, dass Ihre Funktion keinen Prototyp hat. Sie sehen, in C, wenn Sie eine Funktion wie diese deklarieren

int foo();

es deklariert tatsächlich eine Funktion foo das macht eine unbestimmte Anzahl von Parametern unbekannten Typs. Sie können es als nennen

foo(2, 3);

und wie

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

und so weiter (Sie haben die Idee);

Nur der Aufruf mit den richtigen Argumenten wird “funktionieren” (was bedeutet, dass die anderen undefiniertes Verhalten erzeugen), aber es liegt ganz bei Ihnen, für seine Korrektheit zu sorgen. Der Compiler muss die falschen nicht diagnostizieren, selbst wenn er auf magische Weise die richtigen Parametertypen und ihre Gesamtzahl kennt.

Eigentlich ist dieses Verhalten a Besonderheit der C-Sprache. Ein gefährlicher, aber dennoch ein Feature. Es erlaubt Ihnen, so etwas zu tun

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]();
}

dh mischen Sie verschiedene Funktionstypen in einem “polymorphen” Array ohne Typumwandlungen (variadische Funktionstypen können hier jedoch nicht verwendet werden). Auch hier sind die inhärenten Gefahren dieser Technik ziemlich offensichtlich (ich kann mich nicht erinnern, sie jemals benutzt zu haben, aber ich kann mir vorstellen, wo sie nützlich sein kann), aber das ist schließlich C.

Schließlich das Bit, das den zweiten Teil der Antwort mit dem ersten verbindet. Wenn Sie eine Funktionsdefinition im K&R-Stil erstellen, wird kein Prototyp für die Funktion eingeführt. In Bezug auf den Funktionstyp ist Ihre func Definition erklärt func wie

int func();

dh es werden weder die Typen noch die Gesamtzahl der Parameter deklariert. In Ihrem ursprünglichen Beitrag sagen Sie: “… es scheint anzugeben, wie viele Parameter es verwendet …”. Formal nicht! Nach Ihrem Zwei-Parameter-K&R-Stil func Definition können Sie immer noch anrufen func wie

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

und es wird keine Einschränkungsverletzung darin geben. (Normalerweise gibt ein Qualitätscompiler eine Warnung aus).

Auch eine manchmal übersehene Tatsache ist dies

int f()
{
  return 0;
}

ist auch eine Funktionsdefinition im K&R-Stil, die keinen Prototyp einführt. Um es “modern” zu machen, müssten Sie ein explizites setzen void in der Parameterliste

int f(void)
{
  return 0;
}

Schließlich werden entgegen der landläufigen Meinung sowohl Funktionsdefinitionen im K&R-Stil als auch Nicht-Prototyp-Funktionsdeklarationen in C99 vollständig unterstützt. Ersteres ist seit C89/90 veraltet, wenn ich mich recht erinnere. C99 erfordert, dass die Funktion vor der ersten Verwendung deklariert wird, aber die Deklaration muss kein Prototyp sein. Die Verwirrung rührt offenbar von der populären terminologischen Verwechslung her: Viele Leute nennen jede Funktionsdeklaration “einen Prototyp”, während “Funktionsdeklaration” tatsächlich nicht dasselbe ist wie “Prototyp”.

  • Aber was ist nun der Unterschied zwischen einer varargs-Funktion und einer nicht prototypisierten.

    – Sebastian

    26. September 2013 um 9:09 Uhr

  • @Sebastian Godelet Varargs sind unnötig streng. Beispielsweise ist es ungültig, eine vararg-Funktion mit einem int aufzurufen und sie als Bytes zu platzieren. Dasselbe gilt für das Definieren einer Funktion nur mit vararg-Parametern.

    – yyny

    4. Juni 2016 um 21:57 Uhr


  • @Sebastian Vararg Funktionen können tatsächlich mit unterschiedlicher Anzahl von Parametern korrekt aufgerufen werden, wie z printf. Funktionen ohne Prototypen können nur mit einer bestimmten festen Anzahl von Argumenten korrekt aufgerufen werden, aber der Compiler weiß nicht, welches und kann es nicht überprüfen (das müssen Sie also tun).

    – kein Benutzer

    9. April 2019 um 6:28 Uhr

  • Ich schätze, es ist Zeit, sich zu ändern supported even in C99 . C99 to C11. :-).

    – sjsam

    17. April 2019 um 12:45 Uhr

  • @aryndin: In K & R ist der Zweck der Auflistung der Parameter rein intern: um sie zugänglich zu machen Innerhalb die Funktion. Es hat keine Außenwirkung, dh es wird kein Prototyp eingeführt.

    – AnT steht zu Russland

    16. Juli 2021 um 19:25 Uhr

Benutzeravatar von Dirk
Dolch

Dies ist eine ziemlich alte K&R-C-Syntax (vor ANSI/ISO C). Heutzutage sollten Sie es nicht mehr verwenden (da Sie bereits den größten Nachteil bemerkt haben: Der Compiler prüft die Argumenttypen nicht für Sie). Der Argumenttyp ist tatsächlich standardmäßig auf int in deinem beispiel.

Damals wurde diese Syntax verwendet, man fand manchmal Funktionen wie

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

das war eigentlich eine gültige definition, wie die typen für p, qund der Rückgabetyp von foo standardmäßig auf int.

Dies ist einfach eine alte Syntax, die vor der “ANSI C”-Syntax liegt, mit der Sie vielleicht besser vertraut sind. Es heißt “K&R C“, typisch.

Compiler unterstützen es natürlich, um vollständig zu sein und um mit alten Codebasen umgehen zu können.

Benutzeravatar von pmg
pmg

Das ist ein Relikt aus der Zeit, als C noch keine Prototypen für Funktionen hatte. Damals wurde (glaube ich) davon ausgegangen, dass Funktionen zurückkehren int und all seine Argumente wurden angenommen int. Es wurde keine Überprüfung der Funktionsparameter durchgeführt.

Sie sind viel besser dran, Funktionsprototypen in der aktuellen C-Sprache zu verwenden.
Und du muss Verwenden Sie sie in C99 (C89 akzeptiert immer noch die alte Syntax).

Und C99 erfordert, dass Funktionen deklariert werden (möglicherweise ohne Prototyp). Wenn Sie eine neue Funktion von Grund auf neu schreiben, müssen Sie eine Deklaration bereitstellen … machen Sie sie auch zu einem Prototyp: Sie verlieren nichts und erhalten zusätzliche Überprüfungen durch den Compiler.

Dies ist die ursprüngliche K&R-Syntax, bevor C 1989 standardisiert wurde. C89 führte Funktionsprototypen ein, die von C++ entlehnt wurden, und verwarf die K&R-Syntax. Es gibt keinen Grund, es in neuem Code zu verwenden (und viele Gründe, es nicht zu tun).

1418590cookie-checkAlternative (K&R) C-Syntax für Funktionsdeklaration im Vergleich zu Prototypen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy