Действительно ли "&" и "&&" действительно имеют значение для флагов времени компиляции?
У меня есть привычка использовать следующий синтаксис во временных флагах компиляции:
#if (defined(A) & defined(B))
Обычно я предлагал сделать это с помощью &&
следующим образом:
#if (defined(A) && defined(B))
Я знаю разницу между двумя операторами и что в нормальном коде &&
будет короткое замыкание. Тем не менее, все это обрабатывается компилятором. Неважно, что я использую? Это влияет на время компиляции на некоторую бесконечно малое количество, потому что оно не оценивает второй define()
?
Ответы
Ответ 1
Так как defined(SOMETHING)
дает 0 или 1, так что вам гарантировано 0 или 1 с обеих сторон, это не означает, что вы используете &
или &&
.
В основном это касается хороших привычек (использование &
может переноситься в какую-то ситуацию, когда это было бы неправильно) и о написании кода, который легко понять простым сопоставлением шаблонов. A &
там вызывает паузу в миллисекунду, тогда как можно подумать, может ли это быть бит-уровень.
С третьей стороны вы не можете использовать ключевое слово and
, которое вы можете использовать в обычном С++-коде.
Примечания:
¹ С Visual С++ вы можете использовать and
с помощью принудительного включения <iso646.h>
.
Ответ 2
В соответствии со стандартом C99 выражения, используемые в препроцессоре, являются постоянными выражениями, определяемыми самим языком C, и оцениваются с использованием одного и того же движка. Следовательно, &&
является логическим и оператором, что короткие замыкания на основе его LHS, а &
- побитовый оператор без предопределенного порядка оценки.
В практическом плане, когда вы используете с defined()
как есть, между ними нет никакой разницы. Однако следующее может показаться разным:
#define A 2
#define B 5
#if (A && B)
printf("A && B\n");
#endif
#if (A & B)
printf("A & B"\n);
#endif
В этом случае выводится A && B
, но не A & B
(так как результат этого поразрядного и 0
)
Ответ 3
Я хотел бы добавить к предыдущим ответам, что это может иметь большое значение в такой ситуации:
#define A 0
#define B 21
#if (A != 0) && (42 / A == B)
/* ... */
#endif
Здесь, если A == 0
, компилятор не сломается. Запись (A != 0) & (42 / A == B)
заставит компилятор жаловаться на деление на ноль.