Wartość logiczna w ifdef: czy „#ifdef A && B” to to samo, co „#if zdefiniowane (A) && zdefiniowane (B)”?

83

W C ++ jest to:

#ifdef A && B

taki sam jak:

#if defined(A) && defined(B)

?

Myślałem, że tak nie jest, ale nie byłem w stanie znaleźć różnicy w moim kompilatorze (VS2005).

criddell
źródło
1
możliwy duplikat: stackoverflow.com/questions/965700/… Widzę, że są to C i C ++, ale preprocesory są w zasadzie takie same: stackoverflow.com/questions/5085533/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Czy ktoś zacytuje i zinterpretuje standard, aby zdecydować, czy jest legalny, czy nie (na pewno nie powinien działać, ale powinien się kompilować)? Nie jestem w stanie po 15 minutach czytania rozdziału „16 dyrektyw dotyczących wstępnego przetwarzania”.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Odpowiedzi:

92

One nie są takie same. Pierwsza nie działa (testowałem w gcc 4.4.1). Komunikat o błędzie:

test.cc:1:15: ostrzeżenie: dodatkowe tokeny na końcu dyrektywy #ifdef

Jeśli chcesz sprawdzić, czy zdefiniowano wiele rzeczy, użyj drugiej.

Evan Teran
źródło
Dzięki za sprawdzenie. Używam kompilatora Microsoftu i wydaje się, że na to pozwala, ale po prostu nie wydawało mi się to właściwe.
criddell
2
Nie możesz udowodnić rzeczy używając jednego kompilatora. Zapoznaj się ze standardem, który stwierdza, że ​​jest to nieważne.
Wyścigi lekkości na orbicie,
@LightnessRacesinOrbit Jednak niektóre kompilatory rozszerzają standard. Powiedzenie „to działa w pewnym kompilatorze” nie jest próbą udowodnienia, że ​​jest on prawidłowy; jest to zauważenie, że pewien kompilator rozszerza standard w określony sposób.
Załóż pozew Moniki
@QPaysTaxes: Zgoda, ale ta odpowiedź tego nie robi. Odpowiada na pytanie, które zaczyna się „w C ++…” od czegoś, co wydaje się być ogólnym faktem dotyczącym C ++. Na pierwszy rzut oka Evan przetestował swoją teorię na jednym kompilatorze, a następnie założył, że jest ona prawdziwa dla wszystkich, na podstawie gwarancji samego języka. Gdyby stwierdził, że to zachowanie jest rozszerzeniem GCC i powiedział „to jest rozszerzenie GCC” (z odsyłaczem do materiałów referencyjnych), byłoby to w porządku! (choć nie jest to odpowiedź na to konkretne pytanie)
Lightness Races in Orbit
1
Chociaż żadna liczba pozytywnych testów nie może „udowodnić”, że jest ważny, pojedynczy negatywny jest wystarczający, aby udowodnić, że tak nie jest lub że przynajmniej nie jest zalecane jego stosowanie. Odwoływanie się do standardu byłoby miłe, ale udowodnienie, że nie działa on w co najmniej jednym głównym kompilatorze, jest wystarczającym dowodem na stwierdzenie, że „nie działa” na potrzeby tej dyskusji.
zeel
48

Kompilacja warunkowa

Możesz użyć operatora zdefiniowanego w dyrektywie #if, aby użyć wyrażeń, których wynikiem jest 0 lub 1 w wierszu preprocesora. Pozwala to uniknąć używania zagnieżdżonych dyrektyw wstępnego przetwarzania. Nawiasy wokół identyfikatora są opcjonalne. Na przykład:

#if defined (MAX) && ! defined (MIN)  

Bez użycia zdefiniowanego operatora należałoby uwzględnić następujące dwie dyrektywy, aby wykonać powyższy przykład:

#ifdef max 
#ifndef min
Svetlozar Angelov
źródło
2
Chociaż to, co mówisz, jest poprawne, to w ogóle nie odpowiada na pytanie, zapytał, czy te dwa są takie same ... nie są.
Evan Teran
1
Myślę, że jest tam napisane „nie są takie same”, widać, że wyjaśnia, jak utworzyć odpowiednik #if zdefiniowany (COND_A) i zdefiniowany (COND_B), który różni się od #ifdef COND_A && COND_B
Svetlozar Angelov
Tak czy inaczej, jest to przydatna uwaga.
Paul Masri-Stone
2

Następujące wyniki są takie same:

1.

#define A
#define B
#if(defined A && defined B)
printf("define test");
#endif

2.

#ifdef A
#ifdef B
printf("define test");
#endif
#endif
sposób dobry
źródło
1
Czy możesz dodać komentarz, aby opisać, jak to odpowiada na pytanie, nie jest to jasne z Twojej odpowiedzi.
James Wood
Ta odpowiedź, chociaż technicznie poprawna, nie odpowiada dokładnie na pytanie i sugeruje nieprawidłowe użycie. Podczas gdy dwa bloki zrobią to samo, zagnieżdżenie dwóch ifów nie jest tym samym, co użycie &&. Inne warunki, na przykład #else, mogą powodować problem. Tylko pierwsza opcja oznacza dokładnie to, o co prosił pytający.
zeel
1

Dla tych, którzy mogą na przykład szukać (UNIX / g ++), który różni się nieco od OP, może to pomóc:

`

#if(defined A && defined B && defined C)
    const string foo = "xyz";
#else
#if(defined A && defined B)
    const string foo = "xy";
#else
#if(defined A && defined C)
    const string foo = "xz";
#else
#ifdef A
    const string foo = "x";
#endif
#endif
#endif
#endif
MikeB
źródło
Dlaczego nie użyć po prostu #elif zamiast #else #if i na koniec miliarda # endif ...?
Elliott,
-3

Od VS2015 żadne z powyższych nie działa. Prawidłowa dyrektywa to:

#if (MAX && !MIN)

zobacz więcej tutaj

Fabri
źródło
2
Masz link do dokumentacji C #, a nie C ++.
Revolver_Ocelot