Czy możemy pisać komentarze w nazwach zmiennych?

144

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 iasą zdefiniowane globalnie.

Vinita
źródło
13
W „tradycyjnym” języku C sprzed ANSI, przynajmniej w wersji zaimplementowanej przez GNUcpp -traditional , rozszerzałby się do ia = 10;.
Nate Eldredge
37
jakie ciekawe pytanie - dlaczego nigdy wcześniej nie przyszło mi do głowy?
StephenBoesch
178
@javadba: Ponieważ rozsądni ludzie nie pomyśleliby o zrobieniu czegoś takiego?
jamesqf
5
Jeśli naprawdę chcesz to zrobić, możesz przejść na Fortran. Białe znaki na zewnątrz ciągów są usuwane na pierwszym etapie analizy.
mpez0
3
Miałem zamiar zmienić tytuł na „… w nazwach zmiennych…”, ale potem zdałem sobie sprawę, że może rzeczywiście chodziło o „między”. (Chciałem go edytować, ponieważ odpowiedź na oryginalny tytuł brzmi „Dlaczego, oczywiście!”). Ważną częścią jest „brak spacji”.) Czy tytuł „Czy komentarz (bez otaczających spacji) rozdziela tokeny w języku C?” wyrazić swoje aktualne pytanie?
Peter - Przywróć Monikę

Odpowiedzi:

198

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, alub returnsą zdefiniowane jako przerób makr, analizowania program produkuje 14 znaki (nie 13):

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

O ile nie ijest zdefiniowany jako typ z typedefinstrukcją, występuje błąd składniowy, ponieważ i anie 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:

Ale powyższa definicja makra nie definiuje makra podobnego do funkcji, ale zwykłe makro, STATktó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:

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.

chqrlie
źródło
Zastanawiam się, dlaczego Standard wymaga, aby znak odwrotnego ukośnika kontynuacji wiersza nie był oddzielany od nowej linii innymi białymi znakami, biorąc pod uwagę, że nie ma innych okoliczności, w których końcowe spacje lub ich brak byłyby semantycznie znaczące, a niektóre formaty plików tekstowych mogą nie być w stanie odróżnić wiersze kończące się spacjami od wierszy, które go nie kończą?
supercat
@supercat: Zgadzam się. Obejmuje to również przypadek plików pochodzących ze starszych systemów, które używają sekwencji CR LF jako zakończeń linii, powodując błędy kompilacji w systemach uniksowych, które nie rozpoznają \rzmienionych 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:\ 
chqrlie
Standard nie wymaga, aby pliki tekstowe mogły obsługiwać białe znaki na końcu wiersza. Pisanie takiego komentarza, który The path is "C:\"wydawałby się lepszy niż posiadanie znaczenia kodu, zależy od końcowych znaków nowej linii.
supercat
1
Z technicznego punktu widzenia norma nie stawia takiego wymagania, ponieważ często ignorowana faza translacji 1 może usuwać końcowe spacje z każdej linii, o ile jest to udokumentowane.
zwol
4
Ta odpowiedź to długa droga, aby udowodnić, że nie ma głupich pytań. Dobra robota.
Overbryd
65

Z leksykalnego punktu widzenia komentarz jest tym samym, co biały znak.

Sekcja 6.4p3 normy C dotycząca elementów leksykalnych stwierdza:

... Tokeny przetwarzania wstępnego można oddzielić białymi znakami ; składa się z komentarzy (opisanych później) lub znaków odstępu (spacja, tabulator poziomy, nowa linia, tabulator pionowy i wysuw strony) lub obu. ...

Mówiąc dokładniej, komentarz jest tłumaczony na pojedyncze miejsce. Jest to określone w sekcji 5.1.1.2p3:

Plik źródłowy jest dekomponowany na tokeny przetwarzania wstępnego i sekwencje znaków odstępu (w tym komentarze). Plik źródłowy nie może kończyć się tokenem częściowego przetwarzania wstępnego ani częściowym komentarzem. Każdy komentarz jest zastępowany jednym znakiem spacji. Znaki nowego wiersza są zachowywane. To, czy każda niepusta sekwencja znaków odstępu inna niż nowy wiersz jest zachowywana lub zastępowana przez jeden znak spacji, jest zdefiniowana w ramach implementacji.

Aby to zilustrować, jeśli przekażesz swój kod przez preprocesor, otrzymasz:

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.

dbush
źródło
25

Wynik będzie taki, jakbyś napisał:

NIE:

Ken YN
źródło
12

Zobacz tłumaczenie (inaczej kompilacja) Faza 3 , krok 2: „Każdy komentarz jest zastępowany jedną spacją” .

Tak więc, koncepcyjnie, i/*nt*/astaje się i aw tym momencie.

JaMiT
źródło
Komentarze nie służą do rozszerzonej dyskusji; ta rozmowa została przeniesiona do czatu .
Machavity
1

po prostu sprawdź, jaka jest forma twojego kodu

będzie mieć po wstępnym przetworzeniu. Po prostu dodaj flagę „-E” do swojego kompilatora, gcc -E myscript.c, a otrzymasz wynik:

I oczywiście można wywnioskować, że jest błąd.

Eugene W.
źródło
-9

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.

Piyush Chauhan
źródło
5
"nie wpłynie na zmienną. Będzie to samo" To samo co co i alub ia?
HolyBlackCat