Was bedeuten die Klammern um einen Funktionsnamen?

Lesezeit: 4 Minuten

Benutzeravatar von user1859094
Benutzer1859094

In einer meiner Projektquelldateien habe ich diese C-Funktionsdefinition gefunden:

int (foo) (int *bar)
{
    return foo (bar);
}

Hinweis: Neben steht kein Sternchen foo, es ist also kein Funktionszeiger. Oder ist es? Was hat es hier mit dem rekursiven Aufruf auf sich?

  • Nein, es ist kein Funktionszeiger – es ist immer noch eine reguläre Funktion namens foo.

    – Nemanja Boric

    28. November 2012 um 8:29 Uhr

  • Ist das die komplette Funktion?

    – asheshr

    28. November 2012 um 8:30 Uhr

  • Haben Sie Beweise dafür, dass diese Funktion in einem sinnvollen Zusammenhang verwendet wird?

    – muuuuh

    28. November 2012 um 8:32 Uhr

  • … sieht aus wie eine Dummy-Funktion, die vielleicht nur geschrieben wurde, um zu sehen, ob sie in der vorhandenen Quelle kompiliert wird und hätte entfernt werden sollen. Ich würde es entfernen (wenn die Funktion das wirklich tut), da es bestenfalls eine Endlosschleife sein wird (ich bin mir nicht sicher, ob der C-Compiler diesen Tail-Aufruf zum Springen optimieren darf), im schlimmsten Fall ein Stapelüberlauf.

    – Hyde

    28. November 2012 um 8:33 Uhr

  • Klammern in C-Deklarationen helfen, die Sprache mehrdeutig zu machen. Schnell, was ist a(b);? Erklärung von b als Typvariable a? Oder ein Call-to-Function a mit argument b? Der Unterschied ist syntaktisch, und Sie können nicht einmal wissen, wie Sie ihn analysieren können, ohne die Deklarationsinformationen von nachzuschlagen a; dh sind diese Postfix-Funktionsaufruf-Klammern oder optionale Klammern um einen Deklarator.

    – Kas

    28. November 2012 um 20:02 Uhr

Benutzeravatar von NPE
NPE

Da kein Präprozessor-Zeug vor sich geht, fooDie Signatur von ist äquivalent zu

int foo (int *bar)

Der einzige Kontext, in dem ich Leute gesehen habe, die scheinbar unnötige Klammern um Funktionsnamen setzen, ist, wenn es sowohl eine Funktion als auch ein funktionsähnliches Makro mit demselben Namen gibt und der Programmierer eine Makroerweiterung verhindern möchte.

Diese Praxis mag auf den ersten Blick etwas seltsam erscheinen, aber die C-Bibliothek schafft einen Präzedenzfall Bereitstellung einiger Makros und Funktionen mit identischen Namen.

Ein solches Funktions/Makro-Paar ist isdigit(). Die Bibliothek könnte es wie folgt definieren:

/* the macro */
#define isdigit(c) ...

/* the function */
int (isdigit)(int c) /* avoid the macro through the use of parentheses */
{
  return isdigit(c); /* use the macro */
}

Ihre Funktion sieht fast identisch mit der obigen aus, daher vermute ich, dass dies auch in Ihrem Code vor sich geht.

  • Das mag auch hier der Fall sein; Ich habe nicht nach Makros gesucht … Und ich wusste nicht, dass die Makroerweiterung nicht innerhalb von Klammern stattfindet. Danke für den Hinweis!

    – Benutzer1859094

    28. November 2012 um 8:49 Uhr

  • @ user1859094: Auf den zweiten Blick ist dies mit ziemlicher Sicherheit das, was in Ihrem Code vor sich geht. Das foo(bar) Innerhalb der Funktion wird das entsprechende Makro verwendet.

    – NPE

    28. November 2012 um 9:09 Uhr

  • @ user1859094 Makroerweiterung findet innerhalb von Klammern statt, aber die Erweiterung eines funktionsähnlichen Makros findet nur statt, wenn das nächste Token eine linke Klammer ist (C99, 6.10.3§10), also foo (int* bar) würde ersetzt werden, aber nicht (foo) (int *bar) (das nächste Token danach foo ist ))

    – Virgil

    28. November 2012 um 9:48 Uhr


  • Wie würde eine solche Funktion heißen? Würden Sie es auch mit den Klammern aufrufen? Würde das z.B. funktionieren: (isdigit)(5)?

    – gcochard

    5. Dezember 2012 um 19:14 Uhr


  • @Greg: Richtig, genau so würdest du es nennen.

    – NPE

    5. Dezember 2012 um 19:27 Uhr

Die Klammern ändern nichts an der Deklaration – es definiert immer noch nur eine gewöhnliche aufgerufene Funktion foo.

Der Grund, warum sie verwendet wurden, liegt mit ziemlicher Sicherheit darin, dass ein funktionsähnliches Makro aufgerufen wird foo definiert:

#define foo(x) ...

Verwenden (foo) in der Funktionsdeklaration verhindert, dass dieses Makro hier expandiert wird. Was also wahrscheinlich passiert, ist eine Funktion foo() wird definiert, wobei sein Körper aus dem funktionsähnlichen Makro erweitert wird foo.

  • Netter Abzug (obwohl die Verwendung von Klammern zu diesem Zweck strafbar sein sollte).

    – ugoren

    28. November 2012 um 8:47 Uhr

  • @ugoren: Die Verwendung von Klammern um den Funktionsnamen ist ungefähr die einzige Möglichkeit, eine Makroerweiterung für ein funktionsähnliches Makro zu verhindern. Manchmal ist es ein notwendiges Werkzeug.

    – Michael Burr

    28. November 2012 um 9:19 Uhr

  • @MichaelBurr, es gibt auch die Möglichkeit, kein Makro und keine Funktion mit demselben Namen zu haben. Ich weiß, dass Sie nicht immer alles kontrollieren können, aber wenn Sie diese Lösung erreicht haben, würde ich sagen, dass etwas sehr falsch ist.

    – ugoren

    28. November 2012 um 9:23 Uhr

Die Klammern sind bedeutungslos.
Der Code, den Sie zeigen, ist nichts anderes als eine unendliche Rekursion.

Beim Definieren eines Funktionszeigers sehen Sie manchmal seltsame Klammern, die etwas bedeuten. Aber das ist hier nicht der Fall.

  • Offensichtlich nicht; die Klammern verhindern die Makroerweiterung. Siehe akzeptierte Antwort.

    – Kevin

    28. November 2012 um 22:53 Uhr


  • @Kevin, meine Antwort bezieht sich auf den angezeigten Code und ist dafür richtig. In fast jeder C-Frage hier kann die Annahme unbekannter Präprozessordefinitionen alles ändern. In diesem Fall sind Antworten, die den Präprozessor berücksichtigen, zwar besser, aber es macht meine nicht falsch.

    – ugoren

    29. November 2012 um 9:07 Uhr

1426000cookie-checkWas bedeuten die Klammern um einen Funktionsnamen?

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

Privacy policy