Können wir Kommentare in Variablennamen schreiben?

145
int main()
{
     i/*nt*/a = 10;
     return 0;
}

Wenn ich den obigen Code habe und die Token zählen möchte, sind es dann 14 oder 13 Token?

Ist es gültig, einen Kommentar innerhalb eines Variablennamens zu schreiben? Sie können davon ausgehen , dass die int i, int a, int iaglobal definiert.

Vinita
quelle
13
In "traditionellem" C vor ANSI würde es , zumindest wie von GNUcpp -traditional implementiert , auf erweitert ia = 10;.
Nate Eldredge
37
Was für eine interessante Frage - warum ist mir das noch nie in den Sinn gekommen?
StephenBoesch
177
@javadba: Weil vernünftige Leute nicht daran denken würden, so etwas zu tun?
Jamesqf
5
Wenn Sie das wirklich wollen, können Sie nach Fortran wechseln. Leerzeichen außerhalb von Zeichenfolgen werden in der ersten Analysestufe entfernt.
mpez0
3
Ich wollte gerade den Titel in ".... innerhalb von Variablennamen ..." bearbeiten , stellte dann aber fest, dass Sie tatsächlich "zwischen" gemeint haben. (Ich wollte es bearbeiten, weil die Antwort auf den Originaltitel "Warum natürlich!" Lautet. Der wichtige Teil ist "kein Leerzeichen".) Würde der Titel "Trennt ein Kommentar (ohne umgebendes Leerzeichen) Token in C?" Ihre eigentliche Frage ausdrücken?
Peter - Monica

Antworten:

197

Die Kommentare werden in Phase 3 der Programmübersetzung 1 entfernt : Jeder Kommentar wird durch ein Leerzeichen ersetzt. Der Kommentar /*nt*/ist also definitiv kein Zeichen.

Wenn keine des int, main, i, aoder returnwerden als Vorverarbeitung Makros definiert, Parsen des Programms erzeugt 14 - Token (nicht 13):

int main ( ) { i a = 10 ; return 0 ; }

Sofern nicht ials Typ mit einer typedefAnweisung definiert, liegt ein Syntaxfehler vor, i ader nicht mit einer Regel in der C-Grammatik übereinstimmt.

Sie können also keine Kommentare in Variablennamen schreiben. Der Kommentar teilt den Bezeichner in zwei separate Token auf. Dies gilt für alle Vorverarbeitungs- und C-Sprach-Token 2 .

Beachten Sie jedoch, dass Sie Kommentare an ungewöhnlichen Stellen einfügen können, z. B. zwischen unären Operatoren und ihrem Operanden oder zwischen der #und der Vorverarbeitungsanweisung und ihren Argumenten:

/**/#/**/include/**/<stdio.h>/**///////////////////////
/**/#/**/define/**/STAT/**/(/**/a/**/)/**/-/**/1/**////
/**/#/**/ifdef/**/STAT/**//////////////////////////////
/**/int/**/main/**/(/**/)/**/{/**//////////////////////
/**/int/**/a/**/=/**/+/**/1/**/;/**////////////////////
/**/printf/**/(/**/"Hello "/**/"world!\n"/**/)/**/;/**/
/**/return/**/STAT/**/;/**/////////////////////////////
/**/}/**///////////////////////////////////////////////
/**/#/**/endif/**//////////////////////////////////////

Die obige Makrodefinition definiert jedoch kein funktionsähnliches Makro, sondern ein reguläres Makro STAT, das erweitert wird ( a ) - 1.

Variablennamen können wie jedes andere Token durch maskierte Zeilenumbrüche aufgeteilt werden. Escape-Zeilenumbrüche sind Sequenzen oder \unmittelbar gefolgt von einem Zeilenumbruch. Diese Sequenzen werden während der Phase 2 der Programmübersetzung aus dem Quellcode entfernt. Ihr Hauptzweck besteht darin, lange Makrodefinitionen in mehreren Zeilen zu unterbrechen.

Unten ist ein Codefragment 3 , das die gleichen 14 Token erzeugt:

\
i\
nt\
 ma\
in()
{\
i/\
*nt\
*/a \
= 10;
r\
et\
urn\
 0;}

Beachten Sie, dass der Code-Colorizer die in Scheiben geschnittenen und gewürfelten Schlüsselwörter und Kommentare übersehen hat :)


1) Dieses Verhalten wurde in ANSI-C aka C89 angegeben. Einige alte Compiler hatten ein subtil unterschiedliches Verhalten, was zum Einfügen von Token führte, aber solche Besonderheiten sind nur von historischem Interesse.

2) Sie können fast einen Kommentar in eine Zeichenfolgenkonstante einfügen, indem Sie die Tatsache ausnutzen, dass benachbarte Zeichenfolgenkonstanten in Phase 6 der Programmübersetzung verkettet werden: printf("Hello "/* my name is Luca */"world!\n");

3) Dieser Weihnachtsbaum- Präsentationsstil ist nicht für die Verwendung in realen Programmen gedacht. Er zeigt, wie die Eingabeverarbeitungsfunktionen von C missbraucht werden. Ausgefeiltere Tricks haben den International Obfuscated C Code Contest gewonnen

chqrlie
quelle
Ich frage mich, warum der Standard verlangt, dass ein Backslash-Zeichen mit Zeilenfortsetzung nicht durch andere Leerzeichen von der neuen Zeile getrennt wird, da es keinen anderen Umstand gibt, in dem nachgestellte Leerzeichen oder deren Fehlen semantisch bedeutsam wären und einige Textdateiformate möglicherweise nicht in der Lage sein, Linien, die mit Leerzeichen enden, von Linien zu unterscheiden, die dies nicht tun?
Supercat
@ Supercat: Ich stimme zu. Dies würde auch den Fall von Dateien abdecken, die von Legacy-Systemen stammen, die CR-LF-Sequenzen als Zeilenenden verwenden, was zu Kompilierungsfehlern auf Unix-Systemen führt, die nicht entkommene Zeilenumbrüche erkennen, die ein \rvor dem enthalten \n. Es gibt jedoch einen Fall, in dem dies nach hinten const char *path = "C:\\"; // the default path is C:\ 
losgehen
Der Standard verlangt nicht, dass Textdateien Leerzeichen am Ende einer Zeile unterstützen können. Das Schreiben eines Kommentars, The path is "C:\"der besser erscheint als die Bedeutung des Codes, hängt von nachgestellten Zeilenumbrüchen ab.
Supercat
1
Technisch gesehen macht der Standard keine solchen Anforderungen, da die oft ignorierte Übersetzungsphase 1 nachfolgende Leerzeichen von jeder Zeile entfernen darf , solange dieses Verhalten dokumentiert ist.
zwol
4
Diese Antwort reicht weit, um zu beweisen, dass es keine dummen Fragen gibt. Gut gemacht.
Overbryd
65

Aus lexikalischer Sicht entspricht ein Kommentar einem Leerzeichen.

In Abschnitt 6.4p3 des C-Standards zu lexikalischen Elementen heißt es:

... Vorverarbeitungstoken können durch Leerzeichen getrennt werden . Dies besteht aus Kommentaren (später beschrieben) oder Leerzeichen (Leerzeichen, horizontale Registerkarte, neue Zeile, vertikale Registerkarte und Formularvorschub) oder beidem. ...

Insbesondere wird ein Kommentar in ein einzelnes Leerzeichen übersetzt. Dies ist in Abschnitt 5.1.1.2p3 angegeben:

Die Quelldatei wird in Vorverarbeitungstoken und Sequenzen von Leerzeichen (einschließlich Kommentaren) zerlegt. Eine Quelldatei darf nicht mit einem Teilvorverarbeitungstoken oder einem Teilkommentar enden. Jeder Kommentar wird durch ein Leerzeichen ersetzt. Zeilenumbrüche bleiben erhalten. Ob jede nicht leere Folge von anderen Leerzeichen als Zeilenumbrüchen beibehalten oder durch ein Leerzeichen ersetzt wird, ist implementierungsdefiniert.

Um dies zu veranschaulichen, erhalten Sie, wenn Sie Ihren Code durch den Präprozessor übergeben:

  int main()
  {
       i a = 10;
       return 0;

  }

Kommentare wie Leerzeichen dienen also dazu, Token zu trennen.

Dies bedeutet, dass der Code 14 Token enthält, nicht 13.

dbush
quelle
26

Das Ergebnis wird so sein, als hätten Sie geschrieben:

i a = 10;

NICHT:

ia = 10;
Ken YN
quelle
12

Siehe Übersetzung (auch bekannt als Kompilieren), Phase 3 , Schritt 2: "Jeder Kommentar wird durch ein Leerzeichen ersetzt" .

Also, konzeptionell, i/*nt*/awird i aan diesem Punkt.

JaMiT
quelle
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Machavity
1

Überprüfen Sie einfach, welche Form Ihr Code hat

     int main()
    {
        int i/*nt*/a = 10;
        return 0;
    }

wird nach der Vorverarbeitung haben. Fügen Sie einfach Ihrem Compiler das Flag "-E" hinzu, gcc -E myscript.c, und Sie erhalten das Ergebnis:

e.sharaborin@landau:~$ gcc -E myscript.c
# 1 "myscript.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "myscript.c"
int main()
{
    int i a = 10;
    return 0;
}

Und natürlich können Sie daraus schließen, dass ein Fehler vorliegt.

Eugene W.
quelle
-9

Ja, das kannst du machen. Kommentare werden vom Compiler übersprungen. Sie wirken sich nicht auf die Variable aus. Es wird dasselbe sein, aber vergessen Sie nicht, Kommentar-Tags zu beenden.

Piyush Chauhan
quelle
5
"wirkt sich nicht auf die Variable aus. Es wird dasselbe sein" Wie was, i aoder ia?
HolyBlackCat