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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: макросы однако  (Прочитано 10713 раз)
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 » 

nrak,

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

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines