Malaja
|
|
« : 27-11-2008 09:16 » |
|
Господа любители и знатоки макросов, помогите! Я их использовала крайне редко, но до сих пор все обходилось как-то без проблем к нашему обоюдному удовольствию. А тут пришлось опять вспомнить про них родимых. Но в этот раз я была послана компилятором подальше, а почему - не пойму... В студии 2005 создала обыкновенный консольный проект, в нем: #include "stdafx.h"
#define MY_TEST (param1, param2) \ ret = test_macro(param1, param2); \
bool test_macro ( int i, char* pStr ) { }
////////////////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[]) { char s[10]; int i; bool ret; //ret = test_macro(i, s);
MY_TEST (i, s);
return 0; }
Была послана следующим образом: 1>d:\irina\prog\exercises\test_2003\test_2003\test_2003.cpp(22) : error C2065: 'param1' : undeclared identifier 1>d:\irina\prog\exercises\test_2003\test_2003\test_2003.cpp(22) : error C2065: 'param2' : undeclared identifier 1>d:\irina\prog\exercises\test_2003\test_2003\test_2003.cpp(22) : error C2146: syntax error : missing ';' before identifier 'ret'
За что??? Где грабли???
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Вад
|
|
« Ответ #1 : 27-11-2008 09:25 » |
|
define MY_TEST(param1, param2) \ ret = test_macro(param1, param2);
Скобки слитно с именем макроса. Иначе подставляет всё, включая эти самые скобки, на место MY_TEST, игнорируя параметры.
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #2 : 27-11-2008 09:30 » |
|
а ещё не нужно ставить "\" после последней строчки. Также лучше не ставить и ";" в конце макроса
|
|
« Последнее редактирование: 27-11-2008 09:56 от Алексей1153++ »
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #3 : 27-11-2008 09:43 » |
|
Вад, Спасибочки!!! А ларчик просто открывался, когда знаешь, где замочек и имеешь для него ключик! Видимо, до этого я писала правильно, но это была случайность, т.к. насчет пробела я не знала. Леш, я просто автоматом всюду поставила ";" ещё не нужно ставить "\" после последней строчки
Вопрос профана - это где-то потом мешает или как?
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Вад
|
|
« Ответ #4 : 27-11-2008 09:48 » |
|
Malaja, просто следующая за "\" строчка всегда будет подставляться. У тебя она пустая, но мало ли
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #5 : 27-11-2008 09:55 » |
|
Ирин , про ";" - автоматом то и надо расставлять , это всё правильно , просто в сааамом конце макроса лучше имхо не ставить, потому что это ; ты поставишь тогда, когда "вызов" макроса в программе напишешь. Удобно, когда будешь переделывать макрос в функцию
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #6 : 27-11-2008 09:56 » |
|
Вот еще одно глубокое непонимание применения макросов:
#define MY_TEST (param1, param2) \ ret = test_macro(param1, param2); \
Это хорошо что у Вас в функции main определена переменная ret, а если ее не будет, тогда что?
|
|
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #7 : 27-11-2008 10:01 » |
|
Serg79, тут нет непонимания, это просто надо помнить ) Или отразить в названии макроса (или в комментарии). Гораздо опаснее объявление переменных внутри макроса - можно запросто попутать видимость или нарваться на ругань на ошибки компилятора. Когда в макросе объявляешь переменную, её надо обозвать так, чтобы она не пересеклась ни с чем вне макроса, например (почти в идеале) #define MyMacro \ {\ int _MyMacro_nCounter=0;\ ...;\ }
ну и ещё не оставлять пробелы или табуляции после символов "\" (в конце строки) , а то поиски косяка займёт пол дня ))
|
|
|
Записан
|
|
|
|
Serg79
|
|
« Ответ #8 : 27-11-2008 10:23 » |
|
Гораздо опаснее объявление переменных внутри макроса - можно запросто попутать видимость или нарваться на ругань на ошибки компилятора. Когда в макросе объявляешь переменную, её надо обозвать так, чтобы она не пересеклась ни с чем вне макроса, например (почти в идеале) #define MyMacro \ {\ int _MyMacro_nCounter=0;\ ...;\ }
Здесь проблем вообще нет, как хочешь так и называй переменную, т.к. ее область видимости будет ограничена фигурными скобками и все другие переменные с таким же именем будут просто затеняться ею. А вот убедить меня в том, что человек пишущий такую конструкцию: #define MYMACRO(a,b) ret = test_func(a,b); понимает что он делает, у Тебя не получиться .
|
|
« Последнее редактирование: 27-11-2008 10:25 от Serg79 »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #9 : 27-11-2008 10:30 » |
|
ret = test_func(a,b); Serg79, сам так пишу нередко , правда в локальных макросах. Редко - в глобальных , и ничего тут страшного нету ) ну если ты так не делаешь, тогда с видимостью у тебя проблем и не будет Но тогда тебе надо писать не макросы, а функции сразу уж
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #10 : 27-11-2008 10:48 » |
|
Serg79,
во-первых, спасибо за замечение. Дело в том, что это был просто пример, чтобы разобраться, т.к. сначала у меня появились такие ошибки компилятора в реальной программе. Опять же в реальной программе это класс, в котором есть некий набор функций, в которых в свою очередь должны быть использованы макросы. Как в классе, так и в самих функциях объявлены определенные переменные, которые затем используются в макросах (как например та самая переменная ret). Поэтому проблем быть теоретически не должно. Или я опять заблуждаюсь?
Насчет макросов - я их вообще не люблю, т.к. теряется читабельность программы (ИМХО). Но тут я никуда не могу деться - это условие. Дело в том, что впоследствии генератор должен будет создавать наряду с основным классом (речь идет о проге типа rationalRose) дополнительный класс, который должен выполнять определенные функции. я изначально подготовила все в нормальном виде, т.е. функциями, но мен было сказано, что по опыту это потом создает сложности, поэтому все надо перевести в макросы. Вот теперь сижу - перевожу...
Леш, спасибо за замечание насчет объявления переманных в макросе и использования {} ! Сейчас посмотрю и где надо переделаю!
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Serg79
|
|
« Ответ #11 : 27-11-2008 11:02 » |
|
Malaja, вот сравни две конструкции. Первая: int func(int a, int b) { int ret;
MyTest(a,b); return ret; }
Вторая: int func(int a, int b) { int ret;
ret = MyTest(a,b); return ret; }
Вот первый вариант review не пройдет, а это именно то что Ты предлагаешь.
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #12 : 27-11-2008 11:31 » |
|
Serg79, теперь поняла, спасибо! А казалось - такая простая тема, что даже ошибаться и спрашивать стыдно...
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
RXL
Технический
Администратор
Offline
Пол:
|
|
« Ответ #13 : 27-11-2008 17:03 » |
|
Вопрос по теме: в VS можно увидеть код после обработки препроцессором? Это полезно для отладки макросов.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Serg79
|
|
« Ответ #14 : 27-11-2008 18:53 » |
|
Вопрос по теме: в VS можно увидеть код после обработки препроцессором? Это полезно для отладки макросов.
В 6.0 версии это делается ключом /P.
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #15 : 28-11-2008 09:34 » |
|
Serg79,
Возникает вопрос: а где я могу увидеть код? В каком файле? А то я уже вчера этим вопросом задавалась. Но безрезультатно...
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Malaja
|
|
« Ответ #16 : 28-11-2008 15:39 » |
|
Ребята,
нашла вот что: в 2005-ой студии в свойствах проекта (properties): configuration properties -> c++ -> command line -> additional options внести /E.
При этом в output-окне будет выдан реально сгенерированый код. Единственная проблема - компиляция длится значительно дольше, а в окне впоследствии куча инфы кроме той, которая нас интересует. При этом все результаты компиляции находятся также в BuildLog.htm.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Malaja
|
|
« Ответ #17 : 28-11-2008 15:41 » |
|
Еще одно: после "\" в конце строки не может быть пробелов, иначе компилятор тоже ругается! (эта инфа для теких, как я, не для спецов!)
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #18 : 28-11-2008 17:29 » |
|
Malaja, ну и ещё не оставлять пробелы или табуляции после символов "\" (в конце строки) , а то поиски косяка займёт пол дня ))
А ключ /P генерит в папке проекта файлы "*.i"
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #19 : 28-11-2008 18:01 » |
|
Леш, сейчас уже не получится, а в понедельник испробую! О результатах доложу
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
npak
|
|
« Ответ #20 : 29-11-2008 20:35 » |
|
Судя по расширению .cpp, дело происходит в С++. Вопрос - зачем использовать макрос MY_TEST? Специально для того, чтобы избежать всех тех проблем, что обсуждались в этой ветке, в С++ придуманы inline функции. class MyClass { private: bool ret; public: bool test_macro ( int i, char* pStr ); inline void MY_TEST ( int i, char* pStr ); };
void MyClass::MY_TEST( int i, char* pStr ) { ret = test_macro(i, pStr); }
Бонусов сразу вагон. Во-первых, нет таких завихрений с синтаксисом, как в макросах. Во-вторых, гарантируется проверка типов параметров. В третьих, зависимости по внешним переменным провряются на этапе компиляции встроенной функции, а у макроса только в точке подстановки.
|
|
|
Записан
|
|
|
|
Malaja
|
|
« Ответ #21 : 01-12-2008 09:48 » |
|
nrak,
приказы начальства не обсуждаются... В проекте принят свой стиль - я его менять не могу. А то, что это не лучшее и не самое удобное, так я и не спорю - сама это не люблю, т.к. кода не видно, и при поиске ошибок можно повеситься на первом же суку, т.е. макросе... Но в принципе если принять во внимание, для чего оно потом используется (я писала об этом выше), то в некотором смысле логика во всем этом есть.
|
|
|
Записан
|
холоднокровней, Маня, Ви не на работе --------------------------------------- четкое определение сущности бытия: - А мы в прошлом или в будущем?- спросила Алиса. - Мы в жопе, - ответил кролик. - А "жопа" - это настоящее? - спросила Алиса. - А "жопа" - это у нас символ вечности.
|
|
|
|