Warum lässt sich `int ;` in C gut kompilieren, aber nicht in C++?

Lesezeit: 3 Minuten

Benutzer-Avatar
Destruktor

Betrachten Sie das folgende Programm (siehe Live-Demo hier).

#include <stdio.h>
int main(void)
{
      int ;  // Missing variable name
      puts("Surprise");
}

Mein Compiler, gcc 4.8.1, gibt die folgende Warnung aus:

[Warning] nutzloser Typname in leerer Deklaration [enabled by default]

Warum lässt es sich gut kompilieren? Sollte ich nicht einen Compiler-Fehler erhalten? g++ 4.8.1 gibt den folgenden Fehler aus, wenn ich es als C++-Programm kompiliere:

[Error] Deklaration deklariert nichts [-fpermissive]

  • @Nawaz: Wird es explizit durch die Sprachspezifikation gesagt?

    – Destruktor

    22. Oktober 2015 um 4:47 Uhr

  • Im C++-Standard heißt es explizit: “[dcl.dcl]/5 In einem einfache Erklärungdie Wahl Init-Declarator-Liste kann nur weggelassen werden, wenn eine Klasse (Abschnitt 9) oder eine Aufzählung (7.2) deklariert wird, das heißt, wenn die decl-spezifizierer-seq enthält entweder a Klassenbezeichnerein ausgearbeiteter Typbezeichner mit einer Klassenschlüssel (9.1) oder ein Enum-Spezifizierer.” Ich bin mit dem C-Standard nicht gut genug vertraut, um Kapitel und Verse zu zitieren.

    – Igor Tandetnik

    22. Oktober 2015 um 4:54 Uhr


  • “Erzeugt eine Warnung” ist nicht “kompiliert gut”.

    – n. 1.8e9-wo-ist-meine-Aktie m.

    22. Oktober 2015 um 5:13 Uhr

  • Nun, Sie können mehrere Locals gleichzeitig definieren (int a, b, c;), Rechts? int ; sieht nur aus wie ein Sonderfall derselben Sache, mit 0 deklarierten Einheimischen: D

    – Luan

    22. Oktober 2015 um 12:31 Uhr

  • Neu kompilieren mit -Werror

    – David Konrad

    22. Oktober 2015 um 23:07 Uhr

Benutzer-Avatar
n. 1.8e9-wo-ist-meine-Aktie m.

Die C-Norm sagt

Eine andere Deklaration als eine static_assert-Deklaration muss mindestens einen Deklarator (anders als die Parameter einer Funktion oder die Mitglieder einer Struktur oder Vereinigung), ein Tag oder die Mitglieder einer Enumeration deklarieren.

sagt C++

In einer einfachen Deklaration kann die optionale Init-Declarator-Liste nur weggelassen werden, wenn eine Klasse (Klausel 9) oder eine Aufzählung deklariert wird.

Ein Verstoß dagegen in beiden Sprachen erfordert eine Diagnose. Die Standards sprechen nicht über Compilerfehler oder Warnungen. Eine Warnung ist eine Diagnose.

  • Können Sie klarstellen, ob der Standard eine Übersetzung verlangt, um bei bestimmten Verstößen zu scheitern? Ein “Fehler” könnte als eine Verletzung definiert werden, die eine Diagnose und einen Fehler erzeugt, und eine “Warnung” ist eine Verletzung, die eine Diagnose und keinen Fehler erzeugt.

    – Damian Yerrick

    22. Oktober 2015 um 15:24 Uhr

  • @tepples Nein, der Standard erfordert nur eine Diagnose. Es erfordert nicht (erlaubt aber), dass ein ungültiges Programm abgelehnt wird.

    – n. 1.8e9-wo-ist-meine-Aktie m.

    22. Oktober 2015 um 15:44 Uhr


  • es bedeutet, dass zb struct { int a; }; deklariert ein Strukturmitglied, aber das ist nicht genug.

    – n. 1.8e9-wo-ist-meine-Aktie m.

    23. Oktober 2015 um 22:54 Uhr

  • @nm: Hier ist also der Name der Struktur erforderlich. Rechts?

    – Destruktor

    24. Oktober 2015 um 8:41 Uhr

  • Es wird entweder ein Tag oder ein Deklarator benötigt. Etikett ist struct a { ... }. und Deklarator ist struct { ...} a. Ein Deklarator kann ein Variablenname oder ein Typedef-Name sein (falls das Schlüsselwort typedef vorhanden ist).

    – n. 1.8e9-wo-ist-meine-Aktie m.

    24. Oktober 2015 um 11:41 Uhr

Benutzer-Avatar
Ameise

Ihr Code ist sowohl in C als auch in C++ illegal (dh fehlerhaft, schlecht geformt, gegen Einschränkungen verstoßend). Der Grund, warum Sie in einer Sprache eine “Warnung” und in einer anderen einen “Fehler” erhalten, ist nur eine Eigenart Ihres Compilers und Ihres Compiler-Setups. Schließlich unterscheiden beide Sprachen formal nicht wirklich zwischen „Warnungen“ und „Fehlern“. GCC ist unter seinen Standardeinstellungen im C-Modus freizügiger (hauptsächlich aus historischen Gründen).

Verwenden -pedantic-errors in GCC, und Sie erhalten auch einen “Fehler” im C-Code. (Beachten Sie, dass -pedantic-errors wandelt nicht einfach blind alle “Warnungen” in “Fehler” um. Es wird versucht, nur tatsächliche zu melden Beschränkungsverletzungen als “Fehler”.)

Benutzer-Avatar
Yu Hao

Die Syntax der Deklaration ist definiert als (Weglassen Init-Declarator-Liste und Init-Deklarator):

C11 6.7 Erklärungen

declaration:
    declaration-specifiers init-declarator-list opt ;
    static_assert-declaration
declaration-specifiers:
    storage-class-specifier declaration-specifiers opt
    type-specifier declaration-specifiers opt
    type-qualifier declaration-specifiers opt
    function-specifier declaration-specifiers opt
    alignment-specifier declaration-specifiers opt

Beachten Sie, dass Deklarationsbezeichner ist rekursiv definiert, aber jeweils mit einem opt gibt an, dass es optional ist.

Auch die folgende Klausel 6 besagt:

Die Deklarationsbezeichner bestehen aus einer Folge von Bezeichnern, die die Verknüpfung, die Speicherdauer und einen Teil des Typs der Entitäten angeben, die die Deklaratoren bezeichnen. Die initdeclarator-list ist eine durch Kommas getrennte Folge von Deklaratoren, von denen jeder zusätzliche Typinformationen oder einen Initialisierer oder beides haben kann. Die Deklaratoren enthalten die Bezeichner (wenn überhaupt) deklariert werden.

Beachte die Wörter wenn überhaupt.

1015910cookie-checkWarum lässt sich `int ;` in C gut kompilieren, aber nicht in C++?

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

Privacy policy