2012-02-02 15 views
10

W this article z Guru tygodnia, jest powiedziane: It is illegal to #define a reserved word. Czy to prawda? Nie mogę znaleźć niczego w normie i już widziałem programistów na nowo definiujących nowe, na przykład.Czy zmiana definicji słowa kluczowego w C++ jest legalna?

+1

Ostatecznie możliwe jest użycie '# define', aby zmienić znaczenie zarezerwowanych słów. W rzeczywistości jest często używany w zgłoszeniach [The International Obfuscated C Code Contest] (http://www.ioccc.org/). Jest to możliwe, ponieważ makra zdefiniowane przez '# define' są zastępowane przez osobny program przed uruchomieniem właściwego kompilatora C. –

+0

czy nie przeładowali nowego operatora? ponieważ preprocesor działa jako pierwszy, problem polega na tym, że słowa kluczowe "definiuj" zastępują słowa kluczowe ciągiem zastępującym, kod nie spodziewa się, że najprawdopodobniej zostanie zerwany po tym. Zwykle jest to zły pomysł, dlaczego i tak chcesz to robić? – ted

+0

@ted: chodzi o zdefiniowanie nowego słowa kluczowego w pliku źródłowym, aby wywołać implementację specyficzną dla platformy: '#define new newMac' na komputerze Macintosh i' #define new newPc' na PC. W innych jednostkach tłumaczeniowych odpowiednie funkcje będą określać alokatory pamięci specyficzne dla platformy. Myślę, że chodziło o to, aby nadal używać "nowego" wszędzie, mając specyficzne dla platformy zachowanie, gdy nie można zmienić nazwy każdego połączenia na nowe. – qdii

Odpowiedz

18

17.4.3.1.1 nazwy Macro [lib.macro.names]

1 Each name defined as a macro in a header is reserved to the implementation for any use if the translation unit includes the header.164)
2 A translation unit that includes a header shall not contain any macros that define names declared or defined in that header. Nor shall such a translation unit define macros for names lexically identical to keywords.

Nawiasem mówiąc, new jest operatorem i może zostać przeciążone (zastąpiony) przez użytkownika poprzez zapewnienie jego własnego wersja.

+6

Należy zauważyć, że ta reguła dotyczy wyłącznie źródeł zawierających standardowy nagłówek. Zmiana definicji słowa kluczowego jest całkowicie legalna, jeśli jednostka tłumaczeniowa nie zawiera standardowego nagłówka. (Nie ma to jednak większego wpływu na czytelność kodu). –

+1

Mam więc możliwość "#define new", o ile moja jednostka tłumaczeniowa nie zawiera nagłówków: P? @JamesKanze: dlaczego ** standardowe ** nagłówki? – qdii

+0

@victor: biblioteka standardowa (szablonowa) ?? – ted

-1

To nie jest tak daleko, jak jestem świadomy nielegalne - kompilator nie doszedłem jeszcze całej wygeneruje błąd, jeśli nie

#define true false 

#defining pewne słowa kluczowe mogą generować błędy w zestawieniu z innych powodów . Ale wiele z nich spowoduje tylko dziwne zachowanie programu.

+0

Takie definicje mogą powodować problemy z biblioteką standardową. –

+0

Prawdopodobnie w niektórych częściach. Problem polega na tym, że choć jest to nielegalne, nie wydaje się, aby kompilator wymagał wydania diagnostyki. I w zależności od tego, które bity standardowej biblioteki używasz i gdzie umieścisz tę # definicję w swoim kodzie, program mógłby się skompilować dobrze. –

+2

Podobnie jak wiele innych rzeczy, jest to niezdefiniowane zachowanie. Kompilator nie byłby trudny do wykrycia i spowodowałby błąd czasu kompilacji, ale nie wiem o tym. –

11

odpowiednią sekcję z C++ 11:

17.6.4.3.1 Macro nazw [macro.names]

1 A translation unit that includes a standard library header shall not #define or #undef names declared in any standard library header.
2 A translation unit shall not #define or #undef names lexically identical to keywords.

ustępie 1, C++ 03 została usunięta. Drugi akapit został podzielony na dwie części. Pierwsza połowa została teraz zmieniona tak, aby wyraźnie określać, że dotyczy tylko nagłówków standardowych. Drugi punkt został poszerzony o dowolną jednostkę tłumaczeniową, a nie tylko tę, która zawiera nagłówki.

Jednak Przegląd dla tej części standardu (17.6.4.1 [constraints.overview]) stwierdza:

This section describes restrictions on C++ programs that use the facilities of the C++ standard library.

Dlatego też, jeśli nie używasz C++ biblioteki standardowej, a następnie jesteś w porządku, aby robić to, co chcesz.

Aby odpowiedzieć na twoje pytanie w kontekście C++ 11: nie możesz zdefiniować (lub niezdefiniować) żadnych nazw identycznych ze słowami kluczowymi w dowolnej jednostce tłumaczeniowej, jeśli używasz standardowej biblioteki C++.

+0

+1: interesujące – qdii

1

Oto mała rzecz, którą możesz zrobić, jeśli nie chcesz, aby ktoś używał goto. Po prostu upuść gdzieś w swoim kodzie, gdzie go nie zauważy.

#define goto { int x = *(int *)0; } goto 

Teraz za każdym razem, gdy próbuje użyć instrukcji goto, jego program się zawiesi.

+0

Wznowiono dla radości –

+0

@JackAidley tak, ale czy zadałeś sobie pytanie, co sprawia, że ​​jest zabawny? Odpowiedź jest taka, że ​​ludzie są sadystycznymi stworzeniami i to jest strach ... +1 za wskazanie ludzkiej natury. – doc

+4

Jest to niezdefiniowane zachowanie, którego najlepiej unikać. – Abhijit

2

W rzeczywistości są w błędzie, a przynajmniej nie opowiadają całej historii. Prawdziwym powodem, dla którego jest to zabronione, jest to, że narusza zasadę jednej definicji (która nawiasem mówiąc jest również wymieniona jako drugi powód, dla którego jest nielegalna).

Aby zobaczyć, że jest to dozwolone (aby ponownie zdefiniować słowa kluczowe), przynajmniej jeśli nie korzystasz ze standardowych bibliotek, musisz spojrzeć na zupełnie inną część standardu, a mianowicie fazy tłumaczenia. Mówi on, że dane wejściowe są rozkładane na tokeny preprocesora przed rozpoczęciem przetwarzania wstępnego i patrząc na nie ma różnicy między private i fubar, oba są identifiers do preprocesora.Później, gdy dane wejściowe zostaną rozłożone na token, wymiana już się odbyła.

Wskazano, że istnieją ograniczenia dotyczące programów, które mają korzystać ze standardowych bibliotek, ale nie jest oczywiste, że robi to przykład redefiniujący private (w przeciwieństwie do fragmentu "Osoba nr 4: The Language Lawyer") który używa go do wyjścia do cout).

W poprzednim przykładzie wspomniano, że sztuczka nie jest deptana przez inne jednostki tłumaczeniowe lub deptanie po drugiej. Mając to na uwadze prawdopodobnie powinieneś rozważyć możliwość użycia standardowej biblioteki w innym miejscu, które wprowadzi to ograniczenie w życie.

Powiązane problemy