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 ia
global definiert.
c
lexical-analysis
Vinita
quelle
quelle
cpp -traditional
implementiert , auf erweitertia = 10;
.Antworten:
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
,a
oderreturn
werden als Vorverarbeitung Makros definiert, Parsen des Programms erzeugt 14 - Token (nicht 13):int
main
(
)
{
i
a
=
10
;
return
0
;
}
Sofern nicht
i
als Typ mit einertypedef
Anweisung definiert, liegt ein Syntaxfehler vor,i a
der 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
quelle
\r
vor dem enthalten\n
. Es gibt jedoch einen Fall, in dem dies nach hintenconst char *path = "C:\\"; // the default path is C:\
The path is "C:\"
der besser erscheint als die Bedeutung des Codes, hängt von nachgestellten Zeilenumbrüchen ab.Aus lexikalischer Sicht entspricht ein Kommentar einem Leerzeichen.
In Abschnitt 6.4p3 des C-Standards zu lexikalischen Elementen heißt es:
Insbesondere wird ein Kommentar in ein einzelnes Leerzeichen übersetzt. Dies ist in Abschnitt 5.1.1.2p3 angegeben:
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.
quelle
Das Ergebnis wird so sein, als hätten Sie geschrieben:
i a = 10;
NICHT:
ia = 10;
quelle
Siehe Übersetzung (auch bekannt als Kompilieren), Phase 3 , Schritt 2: "Jeder Kommentar wird durch ein Leerzeichen ersetzt" .
Also, konzeptionell,
i/*nt*/a
wirdi a
an diesem Punkt.quelle
Ü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.
quelle
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.
quelle
i a
oderia
?