Menu

Komentarze w C: // i /* */ wyjaśnione

C ma dwa style komentarzy (jednoliniowe // i wieloliniowe /* */) o różnej historii i z jedną pułapką zagnieżdżania. Zobacz, jak używać obu i co warto komentować, a czego nie.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Komentarz to tekst, który kompilator wyrzuca. Istnieje wyłącznie dla ludzi, którzy będą później czytać kod, a jednym z nich zwykle jesteś ty. C oferuje dwie formy, a zrozumienie, kiedy która jest właściwym narzędziem, zajmuje jakieś dwie minuty.

Dwie formy

Uruchom to: wynik ma jedną linię. Oba komentarze zostały usunięte, zanim kompilator w ogóle przeanalizował program; nic nie kosztują w czasie działania i nic nie dodają do pliku wykonywalnego.

// trwa do końca fizycznej linii. Nic nie może stać za nim w tej linii, więc to nie działa tak, jak wygląda:

int x = 5;  // ustaw x na pięć  int y = 6;   /* y nigdy nie zostaje zadeklarowane */

/* ... */ kończy się na pierwszym */, gdziekolwiek ono jest. Może zaczynać się i kończyć w środku linii, co czasem się przydaje:

int total = price /* przed podatkiem */ + shipping;

Dlaczego istnieją dwa style

/* */ to oryginalne C z 1972 roku. // przyszło z C++ i zostało oficjalnie dodane do C dopiero w C99. Ta historia wyjaśnia coś, co zauważysz, czytając starszy kod: biblioteki pisane z myślą o przenośności do C89 używają /* */ nawet dla komentarzy jednoliniowych, bo // nie skompilowałoby się na starych narzędziach, które wciąż wspierały.

Dziś każdy kompilator, którego raczej użyjesz, akceptuje oba. Używaj // do zwykłych uwag, a /* */, gdy komentarz naprawdę zajmuje kilka linii. Jeśli celujesz w bardzo stary kompilator dla systemów wbudowanych, sprawdź to, zanim zaczniesz polegać na //.

Komentarzy nie da się zagnieżdżać

To jedyna prawdziwa pułapka:

/* Na razie wyłącz tę sekcję
   int a = compute();
   /* klasyczna funkcja pomocnicza: miej ją na oku */
   int b = a * 2;
*/

Komentarz blokowy kończy się na pierwszym */, czyli tym w linii 3. Linie 4 i 5 są wtedy znowu żywym kodem, a końcowe */ w linii 6 to błąd składni. Komunikat kompilatora wskazuje ostatnią linię i nic nie mówi o przyczynie.

Rozwiązaniem jest użycie preprocesora, który radzi sobie z zagnieżdżaniem:

#if 0
    int a = compute();
    /* klasyczna funkcja pomocnicza: miej ją na oku */
    int b = a * 2;
#endif

#if 0 nigdy nie jest prawdą, więc preprocesor usuwa wszystko aż do #endif, zanim kompilator to zobaczy. Radzi sobie z komentarzami, cudzysłowami i innymi blokami #if w środku, a przy sprzątaniu łatwo go wyszukać.

Zakomentowywanie kodu podczas debugowania

Tymczasowe usunięcie linii to najczęstsze codzienne zastosowanie komentarzy. Gdy program zachowuje się dziwnie, wyłączanie po jednej instrukcji pokazuje, która z nich ma znaczenie.

Odkomentuj printf i uruchom ponownie, żeby zobaczyć, jak pętla buduje wynik. Śledzenie wypisywaniem nie jest eleganckie, ale w C jest szybkie i zawsze działa: debugger powie ci więcej, a printf powie ci coś od razu.

Dwa nawyki chronią przed bałaganem. Usuwaj zakomentowany kod, zanim zrobisz commit; system kontroli wersji pamięta starą wersję, więc ty nie musisz. A gdy celowo zostawiasz wyłączoną linię, napisz obok, dlaczego.

Komentarze dokumentacyjne

Komentarz blokowy nad funkcją to miejsce, w którym wyjaśniasz, co ona robi, co znaczą jej parametry i co w niej zaskakującego.

Narzędzia takie jak Doxygen czytają takie ustrukturyzowane komentarze i generują z nich dokumentację referencyjną. Własny styl Doxygena używa /** ... */ ze znacznikami @param i @return:

/**
 * Zamienia stopnie Celsjusza na stopnie Fahrenheita.
 * @param c temperatura w stopniach Celsjusza
 * @return ta sama temperatura w stopniach Fahrenheita
 */
double celsius_to_fahrenheit(double c);

Do własnego kodu nada się każdy z nich. Liczy się to, żeby komentarz był obok deklaracji, którą ludzie czytają, zwykle w pliku nagłówkowym, a nie zakopany w implementacji.

Co warto komentować

Zasada, która przetrwa zetknięcie z prawdziwym kodem: komentuj dlaczego, a nie co.

i++;  // zwiększ i          <- nie mówi nic, czego nie powiedział kod
/* Pomiń BOM: pliki eksportowane przez stary system zaczynają się
   od trzech bajtów, które nie są częścią danych. */
offset += 3;

Drugi komentarz zawiera informację, której nie ma nigdzie w kodzie. Pierwszy to szum, który w końcu zacznie przeczyć linii, którą opisuje, bo komentarzy nikt nie aktualizuje, gdy kod się zmienia.

Rzeczy, które w C szczególnie warto skomentować:

  • Kto jest właścicielem tej pamięci. Jeśli funkcja zwraca wskaźnik, który wywołujący musi zwolnić przez free, napisz to. C nie ma jak wyrazić tego w typie.
  • Jednostki i zakresy. int timeout; jest niejednoznaczne: sekundy czy milisekundy?
  • Nieoczywista poprawność. Dlaczego pętla kończy się na n - 1, dlaczego to rzutowanie jest bezpieczne, dlaczego bufor ma 256 bajtów.
  • Celowe dziwactwa. Kod, który wygląda na błąd, ale nim nie jest, przyciąga "poprawki" przyszłych czytelników, chyba że jest opisany.

Ten komentarz zasługuje na swoje miejsce: linia pod nim wygląda na zbędną, a nie jest.

Komentarze w stringach to nie komentarze

Ostatni szczegół. Znaczniki komentarzy nie mają specjalnego znaczenia wewnątrz literału stringowego ani stałej znakowej:

Obie linie wypisują się w całości. Kompilator dzieli stringi na tokeny, zanim zacznie szukać komentarzy, więc // w cudzysłowie to po prostu dwa znaki. (%% w pierwszej linii to sposób na wypisanie dosłownego znaku procentu przez printf: samo % rozpoczyna specyfikator formatu.)

Najczęściej zadawane pytania

Jak napisać komentarz w C?

Na dwa sposoby. // to jest komentarz trwa do końca linii. /* to jest komentarz */ może obejmować dowolną liczbę linii i kończy się na zamykającym */. Oba są usuwane przed kompilacją, więc nigdy nie wpływają na program.

Czy C obsługuje komentarze //?

Tak, od C99. Zostały zapożyczone z C++ i dziś obsługuje je każdy kompilator. Odrzucają je tylko naprawdę stare kompilatory C89, dlatego bardzo stary kod używa /* */ do wszystkiego, nawet do jednej linii.

Czy w C można zagnieżdżać komentarze?

Nie. /* zewnętrzny /* wewnętrzny */ nadal zewnętrzny */ kończy się na pierwszym */, zostawiając nadal zewnętrzny */ jako zepsuty kod. Żeby wyłączyć blok, który już zawiera komentarze /* */, użyj #if 0 ... #endif, które zagnieżdża się poprawnie.

Jak zakomentować blok kodu w C?

Otocz go /* */, jeśli w środku nie ma komentarzy blokowych, albo poprzedź każdą linię //. Solidna opcja dla dużych fragmentów to #if 0 przed i #endif po: preprocesor usuwa wszystko pomiędzy i radzi sobie z komentarzami i cudzysłowami w środku.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ