2010-02-09 19 views
12

, że potrzebny jest sposób, aby zdefiniować FLAGS_IF makro (lub odpowiednik), tak, że#if 0 jako określenie

FLAGS_IF(expression) 
<block_of_code> 
FLAGS_ENDIF 

przy zestawianiu w debugowania (np danego przełącznika kompilatora) kompiluje się

if (MyFunction(expression)) 
{ 
    <block_of_code> 
} 

natomiast w wydaniu nie powoduje żadnych instrukcji, tak jak to było jak to

#if 0 
    <block_of_code> 
#endif 

w moja ignorancja w kwestii preprocesorów C/C++ Nie mogę wymyślić żadnego naiwnego sposobu (ponieważ #define FLAGS_IF(x) #if 0 nawet nie kompiluje) robienia tego, czy możesz pomóc?

muszę rozwiązanie, które:

  • nie dostać zawiedli jeśli */ występuje wewnątrz <block_of_code>
  • z pewnością wygeneruje 0 instrukcjami w wydaniu nawet wewnątrz funkcji inline na każdej głębokości (chyba Wyklucza ? if (false){<block_of_code>} prawej)
  • jest zgodny norma jeśli to możliwe
+4

Jeśli nie kompilujesz całkowicie bez optymalizacji, 'if (fałsz) {kod}' nie umieszcza niczego na wyjściu. –

+0

Och, myślałem, że kompilatory są mniej inteligentne. Dzięki – valerio

+10

Zasadniczo kompilator jest mądrzejszy od Ciebie. Może nie ** ty, ale na pewno ja. –

Odpowiedz

12

Poniższa powinien robić to, co chcesz:

#ifdef DEBUG 
# define FLAGS_IF(x) if (MyFunction((x))) { 
# define FLAGS_ENDIF } 
#else 
# define FLAGS_IF(x) if(0) { 
# define FLAGS_ENDIF } 
#endif 

if (0) powinny przekształcić się żadne instrukcje, albo przynajmniej robi to w większości kompilatorów.

Edit: Hasturkun powiedział, że tak naprawdę nie potrzebują FLAGS_ENDIF, tak byś zamiast pisać kod tak:

FLAGS_IF(expression) { 
    <block_of_code> 
} 

z makrami follow:

#ifdef DEBUG 
# define FLAGS_IF(x) if (MyFunction((x))) 
#else 
# define FLAGS_IF(x) if(0) 
#endif 
+1

Zgaduję, że Valerio szuka prostego sposobu włączania/wyłączania więcej niż jednej funkcji.Twoje rozwiązanie nie jest skalowalne i ukrywa prawdziwą implementację. Rozwiązaniem tego problemu jest użycie zwykłego ifdef. – eyalm

+0

Jeśli tak jest, to naprawdę nie potrzebuję makra FLAGS_IF, które ukrywa instrukcję if. mogę po prostu użyć #define FLAGS_EXP (wyrażenie) 0 if (FLAGS_EXP (wyrażenie)) { } – valerio

2

Jak o coś takiego:

#ifdef DEBUG 
#define FLAGS_IF(expr, block) { if (MyFunction(expr)) block } 
#else 
#define FLAGS_IF(expr, block) 
#endif 

Można go używać tak:

FLAGS_IF(your_favourite_expression, 
    ({ 
    // some code 
    }) 
) 
+0

Tak, tak bym to zrobił – joveha

+1

Zrobiłem to i dławik składni dusić. No cóż. – Joshua

+0

Hm, działa dobrze dla mnie w SlickEdit; nie próbowałem wielu innych. –

4

Dlaczego nie można korzystać z następujących powodów?

 
#ifdef DEBUG 
code for debug mode 
#else 
code for release mode 
#endif 
+0

Nie podoba mi się to, ponieważ wymaga dużo kodu replikacja, wolę umieszczać logikę przełączania wewnątrz makra – valerio

+0

Nie jestem całkiem pewien, jak to się różni od korzystania z makra. Niezależnie od tego, czy używasz #efdef DEBUG, czy używasz prawdziwego makra, wydaje się, że masz prawie dokładnie taką samą ilość duplikacji. Używanie narzędzia #ifdef DEBUG jest bardziej powszechnym sposobem na to, więc jest bardziej prawdopodobne, że ludzie szybciej zorientują się, co robisz, niż powodują problemy z konserwacją. – atk

30

Makra są dość złe, ale nie ma nic złego niż zaciemnianie instrukcji kontrolnych i bloków za pomocą makr. Nie ma żadnego powodu, aby napisać kod taki jak ten. Wystarczy zrobić to:

#ifdef DEBUG 
    if (MyFunction(expression)) 
    { 
    <block_of_code> 
    } 
#endif 
+0

Całkowicie zgadzam się, ale nie mogę sobie pozwolić, aby zrobić to za każdym razem. Makro w tym przypadku jest całkiem użyteczne – valerio

+2

Nie sądzę, aby to rozwiązanie było inne niż to, które zaakceptowałeś w kategoriach pisania. –

+0

Drugi pozwala mi zamknąć #ifdef wewnątrz warunku – valerio

7

mógłbym zrobić coś takiego:

#ifdef DEBUG 
const bool IS_RELEASE_MODE = false; 
#else 
const bool IS_RELEASE_MODE = true; 
#endif 

if (IS_RELEASE_MODE && MyFunction(expression)) 
{ 
    ... 
} 

powinno się skompilowany z wydaniem buduje ze względu na fakt, że jeśli (false & & f()) jest taka sama jak if (false), który zostanie zoptymalizowany w większości kompilatorów.

To znaczy, jeśli nalegasz na niestosowanie kodu #ifdef na wewnętrznej stronie kodu. W przeciwnym razie wolałbym #ifdef DEBUG if (MyFunction (expression)) {...} #endif, którą ktoś opublikował.

+0

Dam to również spróbować – valerio

+0

+1 Zdecydowanie sposób, w jaki pójdę. Zapobiega makrofalowaniu i spowoduje takie same optymalizacje dla większości współczesnych kompilatorów. – 0xC0DEFACE

3

Generalnie staram się unikać zbyt częstego korzystania z kompilacji warunkowej, jeśli to możliwe.

Po pierwsze, jest zwykle brzydka i mniej czytelna.

Ale jeszcze ważniejsze, gdy projekty używać kompilacja warunkowa, aby włączyć debugowanie kodu & off I czasami napotkasz problemy, że debugowanie kodu staje się czerstwy, gdy jest wyłączony. Kiedy chcę użyć tego kodu debugowania, włączam go i ... rzeczy. Nie rób tego. Budować. Już nie.

Kod debugowania może odnosić się do zmiennych lub funkcji, które już nie istnieją lub do rzeczy, które w innym przypadku zostały zmienione na tyle, że nie są już poprawne pod względem składni.

To może być naprawdę irytujące.

Więc ja osobiście podjęte w celu uniknięcia kompilacja warunkowa, aby włączyć/wyłączyć debugowanie kodu na korzyść stosując wyliczenie lub makro (który nadal jest warunkowo skompilowane) do wykorzystania jako warunek w instrukcji if. Po skompilowaniu jako if (0) generowany jest kod środowiska wykonawczego - dokładnie tak, jak jest to pożądane. Ale kod jest nadal kompilowany i sprawdzany pod względem składni, więc zawsze jest przynajmniej poprawny pod względem składniowym.

#if NDEBUG // using the same standard macro that `assert()` uses 
      // use your own if NDEBUG doesn't make sense 
enum { 
    DebugOn = 0 
} 
#else 
enum { 
    DebugOn = 1 
} 
#endif 


// ... elsewhere 

if (DebugOn) { 
    // this always gets compiled, but if it's a release build 
    // the compiler will not emit anything... 
} 

Jak FryGuy mentioned, można łatwo łączyć z tym dzwoni MyFunction() jeśli chcesz - w budowie uwalnianiu, funkcja nie zostanie wywołana na skutek zwarcia, który jest zachowanie określono:

if (DebugOn && MyFunction(expression)) { 
    // this always gets compiled, but if it's a release build 
    // the compiler will not emit anything... 
} 

Ale osobiście, prawdopodobnie używać

if (DebugOn) { 
    if (MyFunction(expression)) { 
     // ... 
    } 
} 

co moim zdaniem pomaga wywołać trochę jaśniej (tylko trochę), że jest to debu blok tylko g.

Ma to zalety polegające na tym, że kompiluje się zawsze i nie ma kontroli przepływu ukrytej za makrami (kilka innych odpowiedzi wymieniło jako złe).

Powiązane problemy