2013-04-26 23 views
41

Nie jest dla mnie jasne, kiedy używam dyrektyw kompilatora, który z poniższych dwóch fragmentów kodu jest poprawny/preferowany i dlaczego. Wygląda na to, że większość programistów i projektów Open Source, które widziałem, korzysta z pierwszej, ale widziałem drugą często używaną.#ifdef DEBUG kontra #if DEBUG

#ifdef DEBUG 
[self doSomethingOnlyWhenDebugging]; 
#endif 

VERSUS

#if DEBUG 
[self doSomethingOnlyWhenDebugging]; 
#endif 

Które z powyższych fragmentów kodu jest korzystne tylko podczas debugowania kodu i dlaczego działa? Domyślam się, że pierwsza uruchomi się, jeśli DEBUG zostanie zdefiniowane jako PRAWDA lub FAŁSZ, gdzie druga będzie działać tylko wtedy, gdy DEBUG jest zdefiniowany i ustawiony na PRAWDA. Czy to jest poprawne?

+9

'' ifdef' po prostu sprawdza, czy symbol został zdefiniowany.'# if' testuje WARTOŚĆ symbolu. więc '#define FOO 0' sprawi, że' #ifdef FOO' będzie prawdziwe, ale '#if FOO' będzie fałszywe, ponieważ robi' #if 0'. –

+0

Powinieneś spróbować znaleźć definicję "root" i określić, czy wartość ma być wartością 1/0, czy obecną/nieobecną. Złapanie ich może mieć "nieoczekiwane" konsekwencje. –

Odpowiedz

35

Masz rację. #if DEBUG nie oceni, czy DEBUG jest zdefiniowane jako 0.

Jak dla kiedy używać każdy, można trzymać się za pomocą #ifdef niczego gdzie trzeba tylko dodać kod jeśli definicja preprocesora jest obecna, takich jak dodawanie rejestrowanie debugowania. Jeśli chcesz sprawdzić wartość i przejść różne ścieżki kompilacji, użyłbym 0 lub 1. Dobrym tego przykładem jest TARGET_IPHONE_SIMULATOR, który jest zawsze zdefiniowany dla projektu iOS, ale tylko 1, jeśli kompilujesz dla symulatora.

+1

Więc jeśli chciałem wykonać pewną linię kodu tylko w Symulatorze, musiałbym użyć '# if', ponieważ' TARGET_IPHONE_SIMULATOR' jest zdefiniowany niezależnie od tego, czy używam Symulatora czy nie. Poprawny? – lidsinker

+2

@lidsinker poprawne – Kevin

+0

dobrze wyjaśnione. Dziękuję bardzo –

6

Jak wiadomo, najlepszym wyborem jest:

#ifndef DEBUG 
    NSLog(@"-1"); 
#elif DEBUG == 0 
    NSLog(@"0"); 
#else 
    NSLog(@"%d", DEBUG); 
#endif 

wtedy poznacie #ifndef DEBUG jest korzystne przede wszystkim innym. Jest prostszy wybór:

#if DEBUG == 0 // DEBUG is not defined or defined to be 0 
    // do sth 
#else 
    // do sth 
#endif 

Jednak jeśli -Wundef kompilator flaga jest włączona, może istnieć ostrzeżenie z #if DEBUG == 0.

1

Należy spojrzeć na kod, w którym DEBUG zostanie zdefiniowany lub niezdefiniowany, i odpowiednio wpisać swój kod. W DEBUG znajdziesz, że nie jest zdefiniowany lub zdefiniowany z wartością 1. Tak więc albo zadziała #if DEBUG lub #ifdef DEBUG.

Dla użytkownika #define, które są pod Twoją kontrolą, polecam, aby zawsze je definiować, o wartości 0 lub 1. Następnie można użyć wartości #if, ale można również użyć ich bezpośrednio w zwykłe instrukcje if lub wyrażenia, dzięki którym Twój kod stanie się bardziej czytelny. A ponieważ jest on zawsze zdefiniowany, możesz użyć "Przejdź do definicji" w Xcode, aby przejść do miejsca, w którym jest zdefiniowany i sprawdź, jak i dlaczego jest ustawiony. Jeśli zamiast tego albo #define lub nie #define wartość, i nie jest zdefiniowana, Xcode nie będzie miał pojęcia, gdzie w kodzie źródłowym nie jest zdefiniowany. Daje również szansę na poszukiwanie błędnych zastosowań. Jeśli "Jump to Definition" nie działa, to wiesz, że źle napisałeś.

BTW obrębie dyrektywy #if każde makro, które nie jest zdefiniowana otrzymuje 0. Więc #if DEBUG będzie działać, jeśli DEBUG nie jest określona, ​​lub jeśli DEBUG jest definiowana jako 0, i nie będzie skompilować jeśli DEBUG jest zdefiniowany jako nic - co powie ci, co jest nie tak, więc możesz to naprawić. Z tego punktu widzenia używanie #if jest lepsze, chyba że nie zostanie skompilowane.