int main()
{
i/*nt*/a = 10;
return 0;
}
Jeśli mam powyższy kod i chcę policzyć tokeny, czy będzie to 14 czy 13 tokenów?
Czy wpisywanie komentarza w nazwie zmiennej jest poprawne? Można założyć, że int i
, int a
, int ia
są zdefiniowane globalnie.
c
lexical-analysis
Vinita
źródło
źródło
cpp -traditional
, rozszerzałby się doia = 10;
.Odpowiedzi:
Komentarze są usuwane podczas fazy 3 tłumaczenia programu 1 : każdy komentarz jest zastępowany jedną spacją. więc komentarz
/*nt*/
zdecydowanie nie jest znakiem.Jeśli żadna z
int
,main
,i
,a
lubreturn
są zdefiniowane jako przerób makr, analizowania program produkuje 14 znaki (nie 13):int
main
(
)
{
i
a
=
10
;
return
0
;
}
O ile nie
i
jest zdefiniowany jako typ ztypedef
instrukcją, występuje błąd składniowy, ponieważi a
nie pasuje do reguły w gramatyce C.Dlatego nie możesz wpisywać komentarzy w nazwach zmiennych, komentarz dzieli identyfikator na 2 oddzielne tokeny. To jest prawdziwe dla dowolnej wyprzedzającym i języka C tokena 2 .
Zwróć jednak uwagę, że możesz wstawiać komentarze w nietypowych miejscach, takich jak między operatorami jednoargumentowymi a ich operandami lub między
#
dyrektywą a preprocessing i jej argumentami:/**/#/**/include/**/<stdio.h>/**/////////////////////// /**/#/**/define/**/STAT/**/(/**/a/**/)/**/-/**/1/**//// /**/#/**/ifdef/**/STAT/**////////////////////////////// /**/int/**/main/**/(/**/)/**/{/**////////////////////// /**/int/**/a/**/=/**/+/**/1/**/;/**//////////////////// /**/printf/**/(/**/"Hello "/**/"world!\n"/**/)/**/;/**/ /**/return/**/STAT/**/;/**///////////////////////////// /**/}/**/////////////////////////////////////////////// /**/#/**/endif/**//////////////////////////////////////
Ale powyższa definicja makra nie definiuje makra podobnego do funkcji, ale zwykłe makro,
STAT
które rozwija się do( a ) - 1
.Nazwy zmiennych, jak każdy inny token, można podzielić za pomocą znaków nowej linii. Znaki nowej linii to sekwencje lub
\
bezpośrednio po nich następuje nowa linia. Sekwencje te są usuwane z kodu źródłowego podczas fazy 2 tłumaczenia programu. Ich głównym celem jest złamanie długich definicji makr w wielu wierszach.Poniżej znajduje się fragment kodu 3, który generuje te same 14 tokenów:
\ i\ nt\ ma\ in() {\ i/\ *nt\ */a \ = 10; r\ et\ urn\ 0;}
Zwróć uwagę, jak kolorizator kodu pomijał słowa kluczowe pokrojone w plasterki i kostkę oraz komentarz :)
1) To zachowanie zostało określone w ANSI-C aka C89. Niektórzy starożytni kompilatorzy zachowywali się nieco inaczej, co skutkowało wklejaniem znaczników, ale takie osobliwości mają jedynie znaczenie historyczne.
2) Możesz prawie wstawić komentarz wewnątrz stałej łańcuchowej, wykorzystując fakt, że sąsiednie stałe łańcuchowe są konkatenowane w fazie 6 tłumaczenia programu:
printf("Hello "/* my name is Luca */"world!\n");
3) Ten styl prezentacji Choinka nie jest przeznaczony do użytku w prawdziwych programach, ilustruje, jak nadużywać możliwości obsługi wejścia C. Bardziej wyszukane sztuczki wygrały Międzynarodowy konkurs na zaciemniony kod C.
źródło
\r
zmienionych znaków nowej linii zawierających znak przed rozszerzeniem\n
. Jest jednak przypadek, w którym mogłoby to przynieść odwrotny skutek: komentarze mogą zawierać znaki \, po których następuje spacja, w szczególności w celu uniknięcia wklejania wierszy:const char *path = "C:\\"; // the default path is C:\
The path is "C:\"
wydawałby się lepszy niż posiadanie znaczenia kodu, zależy od końcowych znaków nowej linii.Z leksykalnego punktu widzenia komentarz jest tym samym, co biały znak.
Sekcja 6.4p3 normy C dotycząca elementów leksykalnych stwierdza:
Mówiąc dokładniej, komentarz jest tłumaczony na pojedyncze miejsce. Jest to określone w sekcji 5.1.1.2p3:
Aby to zilustrować, jeśli przekażesz swój kod przez preprocesor, otrzymasz:
int main() { i a = 10; return 0; }
Tak więc komentarze, podobnie jak spacje, służą do oddzielania tokenów.
Oznacza to, że kod będzie zawierał 14 tokenów, a nie 13.
źródło
Wynik będzie taki, jakbyś napisał:
i a = 10;
NIE:
ia = 10;
źródło
Zobacz tłumaczenie (inaczej kompilacja) Faza 3 , krok 2: „Każdy komentarz jest zastępowany jedną spacją” .
Tak więc, koncepcyjnie,
i/*nt*/a
staje sięi a
w tym momencie.źródło
po prostu sprawdź, jaka jest forma twojego kodu
int main() { int i/*nt*/a = 10; return 0; }
będzie mieć po wstępnym przetworzeniu. Po prostu dodaj flagę „-E” do swojego kompilatora, gcc -E myscript.c, a otrzymasz wynik:
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; }
I oczywiście można wywnioskować, że jest błąd.
źródło
Tak, możesz to zrobić. Komentarze zostaną pominięte przez kompilator. Nie wpłyną one na zmienną. Będzie tak samo, tylko nie zapomnij zakończyć tagów komentarza.
źródło
i a
lubia
?