Frage

Was ist nützlich daran C Syntax - Verwenden von K & R '-Stilfunktionserklärungen?

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 zu geben scheint, ist, wie viele Parameter es verwendet und den Rückgabetyp. Ich denke, Parameter ohne Typen sind irgendwie cool, aber warum erlauben Sie es und die int paranName Nach dem Funktionsklarator? Es ist komisch.

Ist das auch noch Standard c?

War es hilfreich?

Lösung

Die Frage, die Sie stellen, sind wirklich zwei Fragen, nicht eine. Die meisten Antworten haben bisher versucht, das Ganze mit einer generischen Decke "Dies ist K & R Style" -Antworten zu decken, während nur ein kleiner Teil davon etwas mit dem sogenannten K & R -Stil zu tun hat (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 der Funktion verwendet wird Definition

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

Dieser ist eigentlich eine K & R-Funktionsfunktionsdefinition. Andere Antwort haben dies ziemlich gut behandelt. Und eigentlich steckt nicht viel da. Die Syntax ist veraltet, aber auch in C99 immer noch vollständig unterstützt (mit Ausnahme der Regel "No Implizit int" in C99, was bedeutet, dass Sie in C99 die Erklärung von nicht weglassen können p2).

Der zweite Teil hat wenig mit dem K & R-Stil zu tun. Ich beziehe mich auf die Tatsache, dass die Funktion mit "getauderten" Argumenten aufgerufen werden kann. In einem solchen Aufruf findet keine Überprüfung des Parametyps statt. Dies hat sehr wenig mit der K & R-Definition an sich zu tun, aber es hat alles damit zu tun, dass Ihre Funktion keinen Prototyp hat. Sie sehen in C, wenn Sie eine solche Funktion deklarieren

int foo();

Es deklariert tatsächlich eine Funktion foo das macht eine nicht näher bezeichnete Anzahl von Parametern unbekannter Type. Sie können es als als nennen

foo(2, 3);

und wie

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

Ans so weiter (Sie haben die Idee);

Nur der Aufruf mit geeigneten Argumenten funktioniert "funktionieren" (was bedeutet, dass die anderen undefinedes Verhalten hervorbringen), aber es liegt ganz an Ihnen, um ihre Richtigkeit zu gewährleisten. Der Compiler ist nicht erforderlich, um die falschen zu diagnostizieren, auch wenn er die richtigen Parametertypen und ihre Gesamtzahl auf magische Weise kennt.

Tatsächlich ist dieses Verhalten a Besonderheit von c Sprache. Eine gefährliche, aber dennoch ein Merkmal. Es ermöglicht 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]();
}

IE mischen verschiedene Funktionstypen in einem "polymorphen" Array ohne Typecasts (variadische Funktionstypen können hier jedoch nicht verwendet werden). Auch hier sind inhärente Gefahren dieser Technik ziemlich offensichtlich (ich erinnere mich nicht, dass ich sie jemals benutzt habe, aber ich kann mir vorstellen, wo sie nützlich sein kann), aber das ist doch C.

Schließlich ist das Bit, das den zweiten Teil der Antwort auf die erste verknüpft. Wenn Sie eine K & R-Funktionsfunktionsdefinition erstellen, wird kein Prototyp für die Funktion eingeführt. Was den Funktionstyp betrifft, ist Ihr func Definition erklärt func wie

int func();

dh weder die Typen noch die Gesamtzahl der Parameter werden deklariert. In Ihrem ursprünglichen Beitrag sagen Sie "... es scheint festzustellen, wie viele Parameter es verwendet ...". Formell spricht es nicht! Nach Ihrem Zwei-Parameter-K & R-Stil func Definition, die Sie noch anrufen können func wie

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

Und es gibt keinen Einschränkungsverletzung. (Normalerweise gibt Ihnen ein Qualitäts Compiler eine Warnung).

Auch eine manchmal übersehene Tatsache ist das

int f()
{
  return 0;
}

ist auch eine K & R-Funktionsfunktionsdefinition, die keinen Prototyp einführt. Um es "modern" zu machen, müsste man einen expliziten platzieren void In der Parameterliste

int f(void)
{
  return 0;
}

Im Gegensatz zu einer populären Meinung werden sowohl die Definitionen für K & R-Stil als auch nicht prototypisierte Funktionserklärungen in C99 vollständig unterstützt. Ersteres wurde seit C89/90 veraltet, wenn ich mich richtig erinnere. C99 erfordert, dass die Funktion vor dem ersten Gebrauch deklariert wird, aber die Deklaration ist nicht erforderlich, um ein Prototyp zu sein. Die Verwirrung beruht offenbar aus der beliebten terminologischen Mischung: Viele Menschen nennen eine Funktionserklärung "einen Prototyp", während tatsächlich "Funktionserklärung" nicht dasselbe wie "Prototyp" ist.

Andere Tipps

Dies ist eine ziemlich alte K & R C-Syntax (Pre-Datate ANSI/ISO C). Heutzutage sollten Sie es nicht mehr verwenden (da Sie bereits festgestellt haben, dass der Hauptnachteil die Argumente für Sie nicht überprüft). Der Argumentyp ist tatsächlich standardmäßig zu int In Ihrem Beispiel.

Zu dieser Zeit wurde diese Syntax verwendet, manchmal fand man Funktionen wie

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

Dies war tatsächlich eine gültige Definition, wie die Typen für foo, p, und q Standard an int.

Dies ist einfach eine alte Syntax, die die "ANSI C" -Syntax, mit der Sie möglicherweise besser vertraut sind. Es heißt "K & r c", normalerweise.

Compiler unterstützen es, abgeschlossen zu sein und natürlich alte Codebasen zu behandeln.

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

Das ist ein Relikt, als C keine Prototypen für Funktionen hatte. Im weitem (glaube ich) wurden Funktionen angenommen, um zurückzukehren int und all seine Argumente wurden angenommen, um es zu sein int. Es wurden keine Überprüfungen über Funktionsparameter durchgeführt.

Sie verwenden viel besser Funktionsprototypen in der aktuellen C -Sprache.
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 Erklärung abgeben ... Machen Sie sie auch zu einem Prototyp: Sie verlieren nichts und erhalten zusätzliche Überprüfung vom Compiler.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top