Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: макросы однако  (Прочитано 22152 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« : 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'

За что??? Где грабли???  А черт его знает...
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 27-11-2008 09:25 » 

Код:
define MY_TEST(param1, param2) \
ret = test_macro(param1, param2);
Скобки слитно с именем макроса. Иначе подставляет всё, включая эти самые скобки, на место MY_TEST, игнорируя параметры.
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 27-11-2008 09:30 » 

а ещё не нужно ставить "\" после последней строчки. Также лучше не ставить и ";" в конце макроса Улыбаюсь
« Последнее редактирование: 27-11-2008 09:56 от Алексей1153++ » Записан

Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #3 : 27-11-2008 09:43 » 

Вад,

Спасибочки!!!
А ларчик просто открывался, когда знаешь, где замочек и имеешь для него ключик! Ага
Видимо, до этого я писала правильно, но это была случайность, т.к. насчет пробела я не знала.

Леш,

я просто автоматом всюду поставила ";" Ага
Цитата
ещё не нужно ставить "\" после последней строчки

Вопрос профана - это где-то потом мешает или как?
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 27-11-2008 09:48 » 

Malaja, просто следующая за "\" строчка всегда будет подставляться. У тебя она пустая, но мало ли Улыбаюсь
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 27-11-2008 09:55 » 

Ирин , про ";" - автоматом то и надо расставлять , это всё правильно , просто в сааамом конце макроса лучше имхо не ставить, потому что это ; ты поставишь тогда, когда "вызов"  макроса в программе напишешь. Удобно, когда будешь переделывать макрос в функцию Ага
Записан

Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 27-11-2008 09:56 » 

Вот еще одно глубокое непонимание применения макросов:

#define MY_TEST (param1, param2)   \
   ret = test_macro(param1, param2);   \

Это хорошо что у Вас в функции main определена переменная ret, а если ее не будет, тогда что?
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 27-11-2008 10:01 » 

Serg79, тут нет непонимания, это просто надо помнить ) Или отразить в названии макроса (или в комментарии). Гораздо опаснее объявление переменных внутри макроса - можно запросто попутать видимость или нарваться на ругань на ошибки компилятора.
Когда в макросе объявляешь переменную, её надо обозвать так, чтобы она не пересеклась ни с чем вне макроса, например (почти в идеале)

Код:
#define MyMacro \
  {\
    int _MyMacro_nCounter=0;\
    ...;\
  }


ну и ещё не оставлять пробелы или табуляции после символов "\" (в конце строки) , а то поиски косяка займёт пол дня ))
Записан

Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #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 » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #9 : 27-11-2008 10:30 » 

ret = test_func(a,b);
Serg79, сам так пишу нередко , правда в локальных макросах. Редко - в глобальных , и ничего тут страшного нету )

ну если ты так не делаешь, тогда с видимостью у тебя проблем и не будет Улыбаюсь Но тогда тебе надо писать не макросы, а функции сразу уж
Записан

Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #10 : 27-11-2008 10:48 » 

Serg79,

во-первых, спасибо за замечение.
Дело в том, что это был просто пример, чтобы разобраться, т.к. сначала у меня появились такие ошибки  компилятора в реальной программе. 
Опять же в реальной программе это класс, в котором есть некий набор функций, в которых в свою очередь должны быть использованы макросы. Как в классе, так и в самих функциях объявлены определенные переменные, которые затем используются в макросах (как например та самая переменная ret).
Поэтому проблем быть теоретически не должно.
Или я опять заблуждаюсь?

Насчет макросов - я их вообще не люблю, т.к. теряется читабельность программы (ИМХО). Но тут я никуда не могу деться - это условие.
Дело в том, что впоследствии генератор должен будет создавать наряду с основным классом (речь идет о проге типа rationalRose) дополнительный класс, который должен выполнять определенные функции. я изначально подготовила все в нормальном виде, т.е. функциями, но мен было сказано, что по опыту это потом создает сложности, поэтому все надо перевести в макросы.
Вот теперь сижу - перевожу...

Леш, спасибо за замечание насчет объявления переманных в макросе и использования {} ! Сейчас посмотрю и где надо переделаю!
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #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
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #12 : 27-11-2008 11:31 » 

Serg79,
теперь поняла, спасибо! Да-да

А казалось - такая простая тема, что даже ошибаться и спрашивать стыдно...  Скромно так...
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 27-11-2008 17:03 » 

Вопрос по теме: в VS можно увидеть код после обработки препроцессором? Это полезно для отладки макросов.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 27-11-2008 18:53 » 

Вопрос по теме: в VS можно увидеть код после обработки препроцессором? Это полезно для отладки макросов.
В 6.0 версии это делается ключом /P.
Записан
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #15 : 28-11-2008 09:34 » 

Serg79,

Возникает вопрос: а где я могу увидеть код? В каком файле?
А то я уже вчера этим вопросом задавалась. Но безрезультатно...
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #16 : 28-11-2008 15:39 » 

Ребята,

нашла вот что:
в 2005-ой студии в свойствах проекта (properties):
configuration properties -> c++ -> command line -> additional options внести /E.

При этом в output-окне будет выдан реально сгенерированый код. Единственная проблема - компиляция длится значительно дольше, а в окне впоследствии куча инфы кроме той, которая нас интересует.
При этом все результаты компиляции находятся также в BuildLog.htm.
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #17 : 28-11-2008 15:41 » 

Еще одно: после "\" в конце строки не может быть пробелов, иначе компилятор тоже ругается! (эта инфа для теких, как я, не для спецов!)
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #18 : 28-11-2008 17:29 » 

Malaja,
Цитата: мну
ну и ещё не оставлять пробелы или табуляции после символов "\" (в конце строки) , а то поиски косяка займёт пол дня ))

Ага

А ключ /P генерит в папке проекта файлы "*.i"
Записан

Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #19 : 28-11-2008 18:01 » 

Леш,
сейчас уже не получится, а в понедельник испробую! О результатах доложу Ага
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #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); }

Бонусов сразу вагон. Во-первых, нет таких завихрений с синтаксисом, как в макросах. Во-вторых, гарантируется проверка типов параметров. В третьих, зависимости по внешним переменным провряются на этапе компиляции встроенной функции, а у макроса только в точке подстановки.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Malaja
Команда клуба

de
Offline Offline
Пол: Женский

« Ответ #21 : 01-12-2008 09:48 » new

nrak,

приказы начальства не обсуждаются... В проекте принят свой стиль - я его менять не могу. А то, что это не лучшее и не самое удобное, так я и не спорю - сама это не люблю, т.к. кода не видно, и при поиске ошибок можно повеситься на первом же суку, т.е. макросе...
Но в принципе если принять во внимание, для чего оно потом используется (я писала об этом выше), то в некотором смысле логика во всем этом есть.
Записан

холоднокровней, Маня, Ви не на работе
---------------------------------------
четкое определение сущности бытия:
- А мы в прошлом или в будущем?- спросила Алиса.
- Мы в жопе, - ответил кролик.
- А "жопа" - это настоящее? - спросила Алиса.
- А "жопа" - это у нас символ вечности.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines