Ошибки, баги, вопросы - страница 2865

 
Andrey Khatimlianskii:

Есть код:

Первая подстановка меняет VALUE на 10 по всему коду до #undef VALUE, остается вот такое:

Следующая подстановка меняет TMP на 10. Получается

Где я туплю?

вместо TMP подставляется не 10, а именно VALUE, а вот потом, если VALUE определен (вот с этим засада), уже 10

Смотри пошагово:

#define VALUE 10        
#define TMP VALUE       
#undef VALUE            
#define VALUE (TMP*2)

void OnStart(void)
{
   Print(VALUE)
}

Препроцессор честно подставляет внутрь Print

Print((TMP*2));

  ,после чего, опять же все без обмана, подставляет вместо TMP что? Правильно:

Print((VALUE*2));

, после чего стирает все диррективы препроцессора и только после этого, компилятору передается вот это:

void OnStart(void)
{
   Print((VALUE*2));
}
 
Vladimir Simakov:

вместо TMP подставляется не 10, а именно VALUE, а вот потом, если VALUE определен (вот с этим засада), уже 10

Смотри пошагово:

Препроцессор честно подставляет внутрь Print

  ,после чего, опять же все без обмана, подставляет вместо TMP что? Правильно:

, после чего стирает все диррективы препроцессора и только после этого, компилятору передается вот это:

Это не называется "сверху вниз".

 
Andrey Khatimlianskii:

Это не называется "сверху вниз".

Сорри, пока пытался объяснить сам запутался)))

Еще раз:

#define VALUE 10        
#define TMP VALUE       
#undef VALUE            
#define VALUE (TMP*2)

На момент второго определения VALUE, макрос VALUE не определен, поэтому VALUE определяется, как

(VALUE*2)

, ведь TMP у нас как был, так и остался определен VALUE.

А вот TMP, после второго определения VALUE, раскрывается уже в

(TMP*2)

Как-то так))

В препроцессоре подставляется именно то, что есть и не важно, как это и где определено. Поэтому и аккуратно надо с ним. Пример:

#define min(A,B) ((A)<(B)?(A):(B))

long Foo(int x) {return x*x;}

void OnStart(void)
{
   int a=500,
       b=20;
   Print(min(500,Foo(b))); //400
}

,а теперь добавим в функцию злое, а именно - побочный эффект

#define min(A,B) ((A)<(B)?(A):(B))

long Foo(int x){
   Print("Увидивший это второй раз - нубяра vulgaris");
   return x*x;}

void OnStart(void)
{
   int a=500,
       b=20;
   Print(min(500,Foo(b)));
}

И это всего лишь надпись, а если от этой функции депозит зависит?

 

Все можно, макрос только нужно один добавить

#define VALUE 10

MACRO( VALUE, VALUE2 )

#define VALUE   VALUE2*2

void f( int i = VALUE ) { Print( i ); }
void OnStart()
{
        f();
}

Результат: 20

 
A100:

Все можно, макрос только нужно один добавить

Результат: 20

Это очень хорошо. Загадки плохо получается отгадывать.

 
Vladimir Simakov:

Сорри, пока пытался объяснить сам запутался)))

Еще раз:

На момент второго определения VALUE, макрос VALUE не определен, поэтому VALUE определяется, как

, ведь TMP у нас как был, так и остался определен VALUE.

А вот TMP, после второго определения VALUE, раскрывается уже в

Как-то так))

В препроцессоре подставляется именно то, что есть и не важно, как это и где определено. Поэтому и аккуратно надо с ним. Пример:

,а теперь добавим в функцию злое, а именно - побочный эффект

И это всего лишь надпись, а если от этой функции депозит зависит?

смешно) когда дошло)

#define VALUE 10        
#define TMP VALUE       
#undef VALUE     

правильно понял, после отмены подстановки первая строчка уже не 10 а вторая TMP это VALUE, но не 10. Т.е. подстановка это далеко не присваивание.

 
Valeriy Yastremskiy:

смешно) когда дошло)

правильно понял, после отмены подстановки первая строчка уже не 10 а вторая TMP это VALUE, но не 10. Т.е. подстановка это далеко не присваивание.

Да. Подстановка - это именно подстановка, один в один. Просто когда у тебя, при подстановке в код (не путать с директивой препроцессора) макрос VALUE определен, то препроцессор раскрывает дальше TMP->VALUE->10, а если нет, то TMP->VALUE. При этом, в самом коде диррективы препроцессора не участвуют, при компиляции их уже там нет. Пример:

#define VALUE 10
#define TMP VALUE

void OnStart()
{
   Print(TMP); //10
if (false){
   #undef VALUE
   #define VALUE 20
   Print(TMP);}
else Print(TMP); //20
}
 
Vladimir Simakov:

Да. Подстановка - это именно подстановка, один в один. Просто когда у тебя, при подстановке в код (не путать с директивой препроцессора) макрос VALUE определен, то препроцессор раскрывает дальше TMP->VALUE->10, а если нет, то TMP->VALUE. При этом, в самом коде диррективы препроцессора не участвуют, при компиляции их уже там нет. Пример:

Да, если закомментить вторую подстановку VALUE 20, уйдет декларация переменной VALUE и компилятор не увидит ее и заругается)

 
A100:

Все можно, макрос только нужно один добавить

Результат: 20

Сдаюсь)))

Как определен

MACRO

?

 
Vladimir Simakov:

Сдаюсь)))

Как определен

?

Так быстро? Еще не все специалисты подключились... неделю подождем

Подсказка: так тоже работает (но решение немного другое)

#define VALUE1 10
#define VALUE2 5

MACRO2( VALUE1, VALUE12 )
MACRO2( VALUE2, VALUE22 )

#define VALUE1  VALUE12*2
#define VALUE2  VALUE22*3

int f1( int i = VALUE1 ) { return i; }
int f2( int i = VALUE2 ) { return i; }
void OnStart()
{
        Print(f1(),":",f2());
}

Результат: 20:15