Макросы, копируют/вставляют части текста, препроцессор вставит подлинный код; автор макроса надеется, что замена произведет допустимый код.
существует три хороших "подсказки" для преуспевания в этом:
, Нормальный код обычно заканчивается точкой с запятой. Если пользовательский код представления, не нуждающийся один...
doSomething(1) ;
DO_SOMETHING_ELSE(2) // <== Hey? What's this?
doSomethingElseAgain(3) ;
Это означает, что пользователь ожидает, что компилятор произведет ошибку, если точка с запятой будет отсутствовать.
, Но реальная очень хорошая причина то, что в некоторое время, автор макроса должен будет, возможно, заменить макрос подлинной функцией (возможно, встроенный). Таким образом, макрос должен действительно , ведут себя как один.
, Таким образом, у нас должна быть точка с запятой необходимости макроса.
Как показано в ответе jfm3, иногда макрос содержит больше чем одну инструкцию. И если макрос используется в, если оператор, это будет проблематично:
if(bIsOk)
MY_MACRO(42) ;
Этот макрос мог быть расширен как:
#define MY_MACRO(x) f(x) ; g(x)
if(bIsOk)
f(42) ; g(42) ; // was MY_MACRO(42) ;
Эти g
функция будет выполняться независимо от значения [1 113].
Это означает, что нам, должно быть, придется добавить объем к макросу:
#define MY_MACRO(x) { f(x) ; g(x) ; }
if(bIsOk)
{ f(42) ; g(42) ; } ; // was MY_MACRO(42) ;
, Если макрос - что-то как:
#define MY_MACRO(x) int i = x + 1 ; f(i) ;
у Нас могла быть другая проблема в следующем коде:
void doSomething()
{
int i = 25 ;
MY_MACRO(32) ;
}
, поскольку это расширилось бы как:
void doSomething()
{
int i = 25 ;
int i = 32 + 1 ; f(i) ; ; // was MY_MACRO(32) ;
}
Этот код не скомпилирует, конечно. Так, снова, решение использует объем:
#define MY_MACRO(x) { int i = x + 1 ; f(i) ; }
void doSomething()
{
int i = 25 ;
{ int i = 32 + 1 ; f(i) ; } ; // was MY_MACRO(32) ;
}
код ведет себя правильно снова.
существует одна идиома C/C++, которая производит этот эффект:/цикл с условием продолжения:
do
{
// code
}
while(false) ;
/в то время как может создать объем, таким образом инкапсулируя код макроса, и нуждается в точке с запятой в конце, таким образом расширяясь в код, нуждающийся один.
премия?
компилятор C++ оптимизирует далеко/цикл с условием продолжения, как факт его постусловие является ложью, известен во время компиляции. Это означает что макрос как:
#define MY_MACRO(x) \
do \
{ \
const int i = x + 1 ; \
f(i) ; g(i) ; \
} \
while(false)
void doSomething(bool bIsOk)
{
int i = 25 ;
if(bIsOk)
MY_MACRO(42) ;
// Etc.
}
расширится правильно как [1 137]
void doSomething(bool bIsOk)
{
int i = 25 ;
if(bIsOk)
do
{
const int i = 42 + 1 ; // was MY_MACRO(42) ;
f(i) ; g(i) ;
}
while(false) ;
// Etc.
}
и тогда скомпилирован и оптимизирован далеко как [1 138]
void doSomething(bool bIsOk)
{
int i = 25 ;
if(bIsOk)
{
f(43) ; g(43) ;
}
// Etc.
}
Это тоже сработает, и вам не нужно дополнительный класс:
#navigation li li {}
Если у вас есть третий уровень LI, возможно, вам придется сбросить / переопределить некоторые стили, которые они унаследуют от указанного выше селектора. Вы можете настроить таргетинг на третий уровень следующим образом:
#navigation li li li {}
Есть два варианта. Я предпочитаю вариант navigationAlt, поскольку он требует меньше работы в конечном итоге:
< / html>