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

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

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


« : 09-07-2007 05:21 » 

много раз встречал на форуме мнение, что определение своих дефайнов в программе - зло. Но лично я ими пользуюсь и иногда просто невозможно без них (не теряя при этом в удобстве)

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

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

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

« Ответ #1 : 09-07-2007 05:50 » 

Смотря для чего ты используешь дефайн. Если ты с его помощью меняешь порядок компиляции в зависимости от версии и т.п., то в принципе используй на здоровье, а для остального вроде бы есть данные и и методы класса.
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #2 : 09-07-2007 07:19 » 

nikedeforest, смотря что ты понимаешь под порядком компиляции...

давай пойдём от обратного - что не стоит делать через дефайн ? (пример приведи)
я потом сравню - если я делаю что то "недопустимое, тогда уточню вопрос
« Последнее редактирование: 09-07-2007 07:21 от Алексей1153++ » Записан

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

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

« Ответ #3 : 09-07-2007 07:22 » 

ИМХО, не стоит делать макросы и объявлять константы (или как там они называются), т.е.
#define MaxValue 100

Но в принципе не сильно возбраняется делать так
#define bugVersion
#define HomeEdition

#ifdef bugVersion
printf (" ");
...

#ifdef HomeEdition
....



Смысл надеюсь понятен?



« Последнее редактирование: 09-07-2007 07:25 от nikedeforest » Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #4 : 09-07-2007 08:52 » 

вот как раз макросов типа
#define MaxValue 100
 - навалом . Но в последнее время стараюсь объявить через enum

а почему так не стоит делать ?
Записан

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

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

« Ответ #5 : 09-07-2007 09:27 » 

Потому что это по сути ничем не лучше глобальных переменных. Ты же пишешь на С++, создай закрытую переменную внутри класса, в котором ты используешь это значение (для выделения массива или еще чего), инкапсулируй ее. Как выразился Макконнелл - "Скрывайте секреты". Есть глава такая в его книге "Совершенный код", где он призывает скрывать подобные (и не подобные Улыбаюсь ) детали реализации.
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #6 : 09-07-2007 09:36 » 

да вот не всегда так получается
Записан

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

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

« Ответ #7 : 09-07-2007 10:05 » 

А в каких случаях не получается?
Записан

ещё один вопрос ...
Джон
просто
Администратор

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

« Ответ #8 : 09-07-2007 10:57 » 

Лёш, на самом деле никто не сможет тебе ответить на вопрос "почему?". Это всё-равно что спросить почему один любит арбуз, а другой свинной хрящик.

Потому что это по сути ничем не лучше глобальных переменных.

Абсолютно неверно! define (в данном случае) не имеет никакого отношения к переменным. Они не находятся в таблице перепенных они ВОБЩЕ нигде не находятся к моменту компиляции. Об этом позаботится прекомпилятор.

Насчёт того, что define - зло. Бред! С таким же успехом можно утверждать, что столовые приборы - зло, поскольку без них можно обойтись, и кушать например руками.

Данному утверждению нет ни одного доказательства , а вот опровергнуть его можно легко:

В программе, в мат. расчётах во многих местах (чтобы быть совсем точным - в 17ти файлах, 48 классов, всего 397 вхождений) необходимо использовать некую эмпирическую константу, которая равна 423.566783. Через 48 недель, эта константа изменяется и становится равной 273.982647.
И что? Мне надо перелопатить 17 файлов и в каждом поменять значение? Каким образом я должен определить переменную(ые) внутри класса? Или сделать глобальную константу?

А как же быть с системозависимыми? Например MAX_PATH?

define (в данном случае) не имеет также никакого отношения к ООП парадигме. Это просто дополнительная возможность, удобно, читабельно, наконец красиво  оформить код. И С++ здесь совершенно не при чём.

Теперь про макросы.

Нормальная цветовая модель в GDI (COLORREF) для набора кодируется как BGR, что очень неудобно для ввода инфы полученной от дизайнеров, которые все экранные цвета представляют в RGB
Те чтобы видеть в коде "нормальную" цветовую модель, цвета надо преобразовать:

Код:
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))

Таким образом они позоволяют сделать код компактным, а, соответственно, удобочитаемым (легко просматриваемым) в ключевых местах, не загромождая его повторяющимися сложными выражениями.

А вот какой вред от них?
« Последнее редактирование: 09-07-2007 10:59 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
nikedeforest
Команда клуба

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

« Ответ #9 : 09-07-2007 11:03 » 

Сравнение с глобальными переменными здесь образное, а не буквальное. Ну а если это по-вашему лучший способ оформить код, то мне просто нечего сказать.
Записан

ещё один вопрос ...
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #10 : 09-07-2007 12:12 » 

ИМХО макросы полезны, когда они действительно полезны, т.е. когда использование другого подхода или невозможно или крайне не удобно, что для меня равносильно невозможно

Джон, что касается констант занесённых в макроопределение, так это решается простыми константными переменными, они на этапе компиляции имеют привычку подставлятся в код значением, а не переменной.
опять же есть менанизм enum
макрос могут переопределить в другом хередере и ты это увидишь только в виде предупреждения в большом проекте собираемого системой автосборки ты можешь никогда не обратить внимание на это сообщение или забить на него со словами: " А макрос, да фиг с ним", этого не случится при использовании енумов и константных переменных, потому, что компилятор не соберёт проект и ты будешь вынужден обратить внимание на проблему.
по поводу RGB это прекрасно заменяется шаблонную на inline функцию
+ под отладной не всегда можно увидеть чему всёже был равен макрос в точке отладки.

Впрочем приведённые тобой примеры мне кажутся вполне безобидными. Лично мне не нравятся макросы которые разварачиваются в здоровенную функцию или класс(видел я много таких), тяжелова-то в них отлаживаться

Есть у нас в коде пара мест, где такие страшные макросы вполне оправданны по соображениям производительности, но их всего ничего.
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #11 : 09-07-2007 15:20 » 

ну функции я никогда не засовывал в макросы, только исключительно константы или повторяемые много раз кусаки (во время поиска глюка они ещё не макрос, а потом переделываю в макрос после отладки)

ещё делаю такую вещь (где то упоминал)
Код:
#define num      133
#define num_txt "133"

 - где надо, вставляю число, где надо - предопределённую строку

Ну и константы и несложные выражения-формулы
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #12 : 09-07-2007 17:27 » 

Алексей1153++, ну ведь можно написать функцию Жаль что бы небыло повторяющегося(шаблонунную, если лень в типах разбираться), зачем макрос? зачем? Жаль найдут у тебя тестеры ошибку, из макроса данные обратно в код будешь вставлять, во все места, где он используется? в нём же даже брейкпоинт не поставить.

что касается
Код:
#define num      133
#define num_txt "133"

то у нас делают так
Код:
const int num = 133;
const char * num_txt = "133";
enum { ENum = 133, Enum2 = 266};
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #13 : 09-07-2007 18:04 » 

LogRus,
const char * num_txt = "133";
- это глобальная переменная. Не есть хорошо совсем...

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

Записан

RXL
Технический
Администратор

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

WWW
« Ответ #14 : 09-07-2007 19:18 » 

Если кто забыл, есть статьи Михалыча на эту тему - там хорошо объяснено, когда и почему define - вред.

Совсем отказываться от define также не следует.
« Последнее редактирование: 09-07-2007 19:21 от RXL » Записан

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

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #15 : 10-07-2007 05:37 » 

LogRus,
const char * num_txt = "133";
- это глобальная переменная. Не есть хорошо совсем...

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

Сделай переменную статиком Улыбаюсь ИМХО лучше чем макрос.
Повторяющихся кусков кода, то стараемся его всегда выносить в функции даже, если функция маленькая.

что касается статьи от Михалыча, то там импользование макроопределений рассматривается в основном, как некая замена typedef

Согласен, от макроопределений полностью отказаться нельзя(особенно, если тебе нужен страж хедера Улыбаюсь ), как известно всё лекарство и всё яд

Когда я смело использую макросы:
1. Стражи заголовочных файлов(про #pragma once умолчим Улыбаюсь platform specific)
2. Условная компиляция(для разных платформ или отладка/релиз)
3. Передача в функцию переменной и символьного представления имени переменной/класса
4. Нет дрого пути кроме, как использовать макрос
к пукту 4 пример
Код:
#define LOG_DATA(Name, Condition, OutData) \
            if(Condition) \
            { \
                  std::cout << Name << " Data: " << OutData << "\n"; \
            }
используем это дело:
Код:
int func(string& s, int i, long l, bool dump)
{
        LOG_DATA("FUNC", dump, << s << " " << i << " "<< l);
        ...
}
почему этот код не вынести в функцию? потому, что: тогда всегда буду вынужден выполнять формирование строки OutData
не зависимо от условия, а формирование строки может быть очень дорогой операцией
Но и этот код можно заменить при желании на такой, что строка формироваться не будет без использования, если написть класс обёртку с шаблонным оператором <<
примерно, так
Код:
class Logger
{
    bool dump_;
public:
    Logger(const string& name, bool dump):dump_(dump)
    {
        if (dump)
           std::cout << name << ":"
    }

     template<T>
     Logger& operator<<(const T)
     {
          if(dump_)
          {
                  std::cout << T;
          }
          return *this;
     }
}
теперь испольуем его:
Код:
int func(string& s, int i, long l, bool dump)
{
        {
           Logger log("FUNC", dump);
           log << s << " " << i << " "<< l << "\n";
        }
        ...
}
но у нас появляются дополнительные расходы: конструирование/разрушение объекта, дополнительные вызовы << и проверки условия
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #16 : 10-07-2007 05:44 » 

примерно понятно )

зы кстати, никогда ещё не доводилось пользоваться cout
Записан

Vlaor
Гость
« Ответ #17 : 10-07-2007 15:17 » 

О чем может идти речь, если сама Microsoft в своих include файлах использует эти define направо и налево. Зачем например обьявлять переменную, тратить место в памяти (пусть и мелочи) когда есть стандартный выход. Осторожней просто надо быть. О .
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #18 : 10-07-2007 17:02 » 

Vlaor, константны переменные не расходуют память, а экономят. Если подумаешь, то поймёшь почему.
Что касается MS, так это их личное дело.
Записан

Странно всё это....
nikedeforest
Команда клуба

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

« Ответ #19 : 10-07-2007 17:34 » 

Мое не авторитетное мнение хочу заменить следующим:
Бьерн Страуструп 1997г.
Цитата
Макрос почти всегда указывает на недостаток языка программирования, программы или программиста... Если вы используете макросы, значит, вам не хватает возможностей отладчиков, инструментов, генерирующих перекрестные ссылки, средств профилирования и т.д.

Макконнелл "Соверешенный код" 2изд. стр 180
Цитата
Современные языки вроде С++ поддерживают много альтернатив макросам:
-ключевое слово const для объявления констант;
-ключевое слово inline для определения функций, которые будут компилироваться как встраиваемый код
-шаблоны для безопасного в плане типов определения стандартных операций, таких как min, max и т.д.
-ключевое слово enum для определения перечислений;
-директиву typedef для простых замен одного типа другим
Записан

ещё один вопрос ...
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #20 : 10-07-2007 17:48 » 

а ещё хотелось бы, чтоб у макросов была область видимости )
Записан

Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #21 : 11-07-2007 04:54 » 

Алексей1153++, направь заявку в комитет по C++ Улыбаюсь
nikedeforest, поддерживаю.
Записан

Странно всё это....
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #22 : 11-07-2007 04:55 » 

LogRus, Улыбаюсь
Записан

Vlaor
Гость
« Ответ #23 : 11-07-2007 16:40 » 

nikedeforest, Я конечно согласен, вот только не пойму насчет экономии памяти. Может тормоз. Ведь при использовании const выделяется место в секции .rdata, но ведь выделяется же. При define происходит прямая подстановка в код.

Например VC6 скомпилил подобный код.
Код:
1:    void func(int);
2:
3:    #define A 10
4:    const int a = 10;
5:
6:    void main()
7:    {

//инициализация

8:    func(A);
0040B468   push        0Ah
0040B46A   call        @ILT+5(func) (0040100a)
0040B46F   add         esp,4
9:    func(a);
0040B472   push        0Ah
0040B474   call        @ILT+5(func) (0040100a)
0040B479   add         esp,4
10:
11:   }

Замечательно, а что мне делать если я хочу использовать нечто вроде:
Код:
#define B (A + 10)
Записан
npak
Команда клуба

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

« Ответ #24 : 11-07-2007 16:56 » 

> а ещё хотелось бы, чтоб у макросов была область видимости )

#define BLA-BLa-BLA

#undef BLA-BLA-BLA

Ситуация с #define похожа на ситуацию с goto - это было универсальное средство переключения потока управления. Умные люди посидели, подумали, и выделили основные идиомы использования goto в отдельные конструкции - более понятные и безопасные: циклы, прерывания циклов (break, continue), вызовы функций и return. Затем подумали и победили экстремальную форму goto - longjump - ввели исключения.

Также и define - универсальное средство управления кодом. Разработчики С++ приложили массу усилий по созданию заменителей define. Во-первых, замена литералов вида
#define MY_MAGIC_NUMBER 123
на константы
const int my_magic_number = 123
которые можно использовать всюду, где в Си разрешаются только литералы (например, задать размер массива - константы enum в Си для этого недопустимы).
Во-вторых, "маленькие" и "быстрые" функции поддержаны функциями inline.
В-третьих, переиспользование кода для разных типов решено введением шаблонов.

Пожалуй, в Си++ не нашли заменителя для одного сценария использования #define - условной компиляции. Более того, такой сценарий использования макросов перекочевал в С# почти в неизменном виде.
Записан

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

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

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

« Ответ #25 : 11-07-2007 17:01 » 

Vlaor, при использовании const компилятор С++ имеет полное право подставить в точку использования константы её фактическое значение, что полностью эквивалентно константам #define. Если константа статическая (то есть не может использоваться за пределами модуля), то оптимизатор может ее выкинуть из секции данных, расставив во всех местах использования фактическое значение.
Записан

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

http://www.unitesk.com/ru/
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #26 : 11-07-2007 17:01 » 

npak, про undef я в курсе. Пользуюсь )
Но стоит поменять имя макроса и забыть поменять его в ундефе - приехали
Записан

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

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

« Ответ #27 : 12-07-2007 09:21 » 

препроцессор по стандарту не парсит текст программы, он только совершает замены и подстановки, и это правильно. С++ сам по себе черезмерно навороченный язык, если к этому добавить семантически подкованный препроцессор - это будет совсем труба. Нужно будет определить понятия границ видимости, определить правила обработки макросов за пределами этих границ, потом может возникнуть желание ввести динамически определенные макросы - проблем будет гораздо больше, чем обретенных возможностей.

Я предлагаю в языке С++ использовать макросы только для условной компиляции. Во всех остальных случаях искать решения средствами языка.
Записан

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

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

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

« Ответ #28 : 12-07-2007 09:58 » 

аминь
Записан

ещё один вопрос ...
Scorp__)
Молодой специалист

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

« Ответ #29 : 10-08-2007 10:56 » 

Да, вот еще особенность макросов съевшая минут 15 времени. Пишу интерфейс под .NET, нужно зарегистрировать горячую клавишу, в этом случае можно воспользоваться только API-шной RegisterHotKey. Отлично, подключаем windows.h. В случае неудачи хочу вывести MessageBox и пользуюсь классом MessageBox для этого, вроде все правильно, пространство имен указал. А компилятор говорит, неа, MessageBoxA() не член этого пространства имен и все тут.

Казалось бы причем тут вообще MessageBoxA(), я его даже не трогаю. Оказывается, в windows.h есть макрос
#define MessageBox MessageBoxA
препроцессор все правильно заменяет, а я сижу и смотрю тупо в монитор пытаясь понять в чем же дело. Решение-то простое:
#undef MessageBox
но все равно неприятно.
Записан

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

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


« Ответ #30 : 10-08-2007 11:37 » 

Scorp__), примени MessageBoxEx Улыбаюсь
Записан

Scorp__)
Молодой специалист

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

« Ответ #31 : 10-08-2007 15:15 » 

Алексей1153++, да решение-то я нашел и описал в своем посте Улыбаюсь Но вот странное предложение для того чтобы отвязаться от применения одной АПИ функции применить другую? Улыбаюсь

Дело в том, что в .NET MessageBox - это класс такой, а всякий кто хочет показать окошечко с сообщением вызывает статический метод этого класса, Show, с нужным набором параметров. Так вот макрос обитающий в windows.h перекрыл название этого класса в namespace System::Windows::Forms.

API функции применять, когда находишься в управляемом (managed) контексте, - довольно недешевое удовольствие и делать это надо только в случае, если другого выхода нет
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
LifeMaker
Гость
« Ответ #32 : 01-06-2008 09:32 » 

вот как раз макросов типа
#define MaxValue 100
 - навалом . Но в последнее время стараюсь объявить через enum

а почему так не стоит делать ?


пакость от такого использования:

Код:

// объявил
#define MaxValue 100

int m[MaxValue]; //использовал

//забыл

... //500 строк кода

void func(int MaxValue) //компилятор нас обматюкает, и придётся долго разбираться почему.
{
  //ещё хуже, если этот MaxValue был объявлен в каком-нибудь библиотечном хидере, а создатель функции случайно выбрал такое же имя
}

правильная альтернатива:
Код:
const int MaxValue = 100;
эффект - тот же, безопасность - выше.
Записан
RXL
Технический
Администратор

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

WWW
« Ответ #33 : 01-06-2008 09:58 » 

Потому и принято в именах макросов и констант использовать только прописные буквы, чтобы не путать с именами переменных.

Кстати, имена переменных тоже не следует начинать с прописной буквы - так принято начинать имена типов (классов).

Все становится просто и ясно:
MAXVALUE - макрос
MaxValue - класс
maxValue - переменная или ф-ия
« Последнее редактирование: 01-06-2008 10:05 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #34 : 01-06-2008 09:59 » 

LifeMaker,

1) первое. "//забыл" - так не будет , скорее всего, потому что стараюсь не забывать и делать ундефайны Ага
2) //компилятор нас обматюкает, и придётся долго разбираться почему. - компилятор напишет что нибудь вроде "повторный идентификатор" или "неправильное использование константы". А поскольку я помню, что за константа (имена обычно говорящие даю, да начинаются с def_) - жмём F12 (для студии) и летим к определению. Или по памяти находим.
3) const - не всегда можно применить так гибко, как макрос, к сожалению. А так бы я давно отказался от дефайнов
Записан

LifeMaker
Гость
« Ответ #35 : 01-06-2008 10:10 » 

А как же быть с системозависимыми? Например MAX_PATH?

по хоршему можно было объявить const int MAX_PATH = <чего-то там>;
и был бы тот же эффект, только немного безопаснее. можно было в другой области видимости использовать MAX_PATH по другому.
а почему этого не сделали - дык эта константа писалась на языке С ещё в те времена, когда стандарта C++ не было. только и всего.
и использование #define в хидерах микрософта для констант объясняется только желанием сохранить совместимость со старыми C компиляторами. зачем программисту, который пишет программу, которая будет компилиться только одним современным хорошим С++ компилятором поступать также?
вообще, перед тем как подражать тому стилю, что используют в Microsoft, Borland и т.д., стоит трижды подумать почему они так сделали и подходит ли такая стратегия вам...

Теперь про макросы...

...они позоволяют сделать код компактным, а, соответственно, удобочитаемым (легко просматриваемым) в ключевых местах, не загромождая его повторяющимися сложными выражениями.

А вот какой вред от них?
а как насчет такого макроса?
Код:
#define sq(val) ((val)*(val)) //возведение в квадрат

int a = sq(3);    //всё замечательно, раскроется в "int a = ((3)*(3))"
int b = sq(sin(a)); //плохо: "int a = ((sin(a))*(sin(a)))" два вызова sin вместо  одного, а могла быть очень сложная конструкция
int c = sq(db->query("<сложный долгоий запрос>").IntValue()); //думаю понятно, почему плохо
int d = sq(object.getValue()); // а если getValue() модифицирует состояние объекта. будет две модификации вместо одной
все проблемы отпадут, если использовать правильную безопасную альтернативу:
Код:
template<class T>
inline T sq(const T& a)
{
   return a*a;
}

да, такая запись чуть длиннее, но она безопасна и кроме того, появляется возможность сделать разную реализацию для разных типов.
например:
Код:
template<class T>
inline T min(const T& a, const T& b)
{
   return a<b;
}

template<const char*>
inline const char* min(const char* a, const char* b)
{
   return (strcmp(a,b)<0) ? a : b;
}

а вот сможешь ли ты написать макросом такой min, который работает и для строк, и для int, float и т.п.?
причем вред от макроса в том, что стоит перед этими шаблонами кому-то написать (в хидере например) макрос #define min(a,b) (a<b?a:b)
и весь мой код будет убит. это я о вреде макросов...
Записан
LifeMaker
Гость
« Ответ #36 : 01-06-2008 10:15 » 

RXL, Алексей1153++, не спорю, хороший стиль может решать некоторые проблемы, но вы боретесь с искуственными проблемами, зачем?
и приведи пример обяъявления константы, где гибкисти const не хватает...
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #37 : 01-06-2008 11:54 » 

>>два вызова sin вместо  одного

это сразу надо учитывать в макросах, это не есть минус. Шаблоны тож не приплетай, речь не о создании универсальных классов Улыбаюсь

примеры, когда константа не катит, не могу сразу вспомнить, просто помню, что были такие ситауции
Записан

LifeMaker
Гость
« Ответ #38 : 01-06-2008 12:12 » 

>>два вызова sin вместо  одного
это сразу надо учитывать в макросах, это не есть минус. Шаблоны тож не приплетай, речь не о создании универсальных классов Улыбаюсь
почему не приплетать шаблоны? это правильная типобезопасная, подчиняющаяся правилам областей видимости замена таким вот макросам. что ты имеешь против шаблонов?
и классов никаких я не создавал. я объявил шаблонную функцию, которая заменяет макрос, и избавляет нас от его недостатков
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #39 : 01-06-2008 12:59 » 

LifeMaker, я ничего не имею против шаблонов Улыбаюсь Открою страшную тайну: я никогда не пользовалься шаблонами
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #40 : 01-06-2008 22:12 » 

LifeMaker,
Есть ряд очень специфичных случаев которые не одойти без макросров (я не смог), один из таких на форуме когда-то обсуждался (мной точно и помоему пушистый с зайцем участвовали), если очень надо ))) могу поискать.

во всем остальном, полностью согласен

Алексей1153++ и RXL, по поводу того, что могут быть проблемы при использовании дефайнов и их объявлении - так это может быть в сторонней библиотеке или этот код содержится в дорабатываемом уже написанном приложении или его просто напишет ваш коллега (допустим стиль написания кода в компании не утвержден)
Записан

С уважением Lapulya
LifeMaker
Гость
« Ответ #41 : 02-06-2008 05:23 » 

Есть ряд очень специфичных случаев которые не одойти без макросров (я не смог), один из таких на форуме когда-то обсуждался (мной точно и помоему пушистый с зайцем участвовали), если очень надо ))) могу поискать.
Не спорю, что есть случаи. Первый - строковый литерал, насколько я знаю, константой не объявишь без лишней переменной. придётся писать
Код:
#define MY_STR "Hello, world!"
и это будет эффективнее чем
Код:
const char* MY_STR = "Hello, world!";
но проблема эффективности тут немного надуманная, на практике я предпочту второй вариант.

Ещё случай. Совсем недавно я на работе писал функцию WRITE_LOG и сделал её макросом по двум причинам.
Во-первых, чтобы в RELEASE-версии была возможность #idef-ом отключить логгирование, во вторых,
потому что gcc компилятор (мы и его на работе используем) умеет распознавать ошибки типа fprintf(f,"%d","string") и только при подстановке макросом не теряется связь <форматная строка>+<передаваемые параметры>.

Случаи действительно специфичные... я собственно почему тут критикую... Алексей1153++ и Джон и другие сторонники дефайна ратуют за типичное использование, именно там где его легко избежать. ни  одного действительно необходимого случая они не привели....
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #42 : 02-06-2008 11:35 » 

LifeMaker,

Цитата
Случаи действительно специфичные... я собственно почему тут критикую... Алексей1153++ и Джон и другие сторонники дефайна ратуют за типичное использование, именно там где его легко избежать. ни  одного действительно необходимого случая они не привели....
Если надо могу привести

Цитата
но проблема эффективности тут немного надуманная, на практике я предпочту второй вариант.
Я безусловно предпочту второй вариант, однако повторяю есть случаи когда вариант без дефайна серьезно грамоздкий и не решает задачу в общем виде. Ща найду... ну вот тут, что-то на тему...
https://forum.shelek.ru/index.php/topic,4744.msg87889.html#msg87889

А вот пример с WRITE_LOG эээ нууу противоречит твоим высказываниям... тут как раз макрос обходится на раз два... причем с возможностью отключением функционала #ifdef
Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #43 : 02-06-2008 15:11 » 

LifeMaker, умеешь обходиться без дефайна - плюс тебе, я не умею Улыбаюсь Например те же строки.

#define MY_STR "Hello, world!"

const char* p="text1"MY_STR"text2";
Записан

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

ru
Offline Offline
Пол: Мужской
Я странный


WWW
« Ответ #44 : 02-06-2008 17:50 » 

а как быть например с:
Код:
#ifndef SOME_H_INCLUDED
#define SOME_H_INCLUDED
...
...
...
#endif
Записан

The CBO without stats is like a morning without coffee. (c) T.Kyte.
LifeMaker
Гость
« Ответ #45 : 02-06-2008 17:59 » 

А вот пример с WRITE_LOG эээ нууу противоречит твоим высказываниям... тут как раз макрос обходится на раз два... причем с возможностью отключением функционала #ifdef
так что бы не было даже вызова пустой функции + вычисление кучи параметров?


тут, опять же, немножко надуманная проблема производительности.
и воспользовался я макросом не из-за отключабельности, а из-за того, что не хотел терять warning'ов, ибо реально полезная вещь. несколько раз уберегала от ошибок...
« Последнее редактирование: 02-06-2008 18:02 от LifeMaker » Записан
LifeMaker
Гость
« Ответ #46 : 02-06-2008 18:08 » 

а как быть например с:
Код:
#ifndef SOME_H_INCLUDED
#define SOME_H_INCLUDED
...
...
...
#endif

#pragma once

и не надо говорить о нестандартности и непортируемости. msvc понимает, с++builder, gcc понимает...
меня удивляет, когда люди упорно отказываются от #pragma once предпочитаю эту конструкцию из-за стандартности, да;t tckb точно знают, что программа завязана на текущий компилятор и никогда не будет собираться другим компилятором.

я когда то тоже так делал. теперь мне за это стыдно
Записан
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #47 : 02-06-2008 18:46 » 

LifeMaker,
а мне не стыдно, не вижу почему надо использовать прагму... Где хоть один плюс? А минус пусть и надуманный (хотя это очень спорно, но флеймить не хочу) на лицо!

Цитата
так что бы не было даже вызова пустой функции + вычисление кучи параметров?
Конечно, вообще ничего вызываться не будет. Запихай вызов между ifdef и endif и все в шоколаде. Если лениво каждый раз писать так много ))) но готов пожертвовать созданием объекта (без мемберов) на стеке, то заказтай в структуру типа так
Код:
struct LoggerWrapper
{
LoggerWrapper ()
{
#ifdef DEBUG
theLogger.write("nmabssfnmsb nms");
#endif
}
};
ну или что-то вроде того
Записан

С уважением Lapulya
LifeMaker
Гость
« Ответ #48 : 02-06-2008 20:22 » 

LifeMaker,
а мне не стыдно, не вижу почему надо использовать прагму... Где хоть один плюс? А минус пусть и надуманный (хотя это очень спорно, но флеймить не хочу) на лицо!

прагма удобнее. простой способ сделать простую вещь. одна строка вместо трёх.
не болтается сбивающий с толку #endif в конце файла который сильно оторван от других строк, с которыми он неразрывно связан.

и кстати как раз сегодня мне эта конструкция немного нервы попортила. мне понадобилось модифицировать h-файл, написанный не мной. загнал туда определение своего класса. компилятор начал меня материть. посмотрел на #ifndef-#define вроде всё как надо.
попробавл и так и эдак. потратил минут 15 (файл входил в precompiled header, каждая попытка скомпилить длилась довольно долго).
выяснилось что структура файла такова

#ifndef __HEADER_SUPER_MACROS
#define __HEADER_SUPER_MACROS
//много всяких объявлений
#endif

#idef _MEGA_PARAMETER1
//много объявлений
#else
//много объявлений
#endif

#idef _MEGA_PARAMETER2
//много объявлений
#else
//много объявлений
#endif

т.е. не весь хидер оказался обрамлён #ifndef-ом. хотя первоначальный взгляд говорит, что вот, всё хорошо. в начале файла #ifndef-#define, а в конце - #endif, а после внимательного чтения всего (!) хидера, оказывается, что не всё так просто...
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #49 : 02-06-2008 20:29 » 

LifeMaker, кстати, в студии есть удобная штука для таких случаев -

#ifndef //{
...километры
...строк
#endif //}

если поставить курсор около фигурной скобки и нажать ctrl+} , то курсор будет перемещён к парной скобке. Если ещё и шифт удержать - всё это выделится
Записан

Scorp__)
Молодой специалист

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

« Ответ #50 : 02-06-2008 20:31 » 

Есть искусственный способ ))

#ifndef __HEADER_SUPER_MACROS
#define __HEADER_SUPER_MACROS
//... код...
#endif // __HEADER_SUPER_MACROS
Сразу видно какой #endif, что закрывает.

Между прочим, Саттер и Александреску рекомендуют использовать именно этот вариант защиты от повторного включения, а не прагмы компиляторов )
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
LifeMaker
Гость
« Ответ #51 : 02-06-2008 20:38 » 

Цитата
так что бы не было даже вызова пустой функции + вычисление кучи параметров?
Конечно, вообще ничего вызываться не будет. Запихай вызов между ifdef и endif и все в шоколаде. Если лениво каждый раз писать так много ))) но готов пожертвовать созданием объекта (без мемберов) на стеке, то заказтай в структуру типа так
Код:
struct LoggerWrapper
{
LoggerWrapper ()
{
#ifdef DEBUG
theLogger.write("nmabssfnmsb nms");
#endif
}
};
ну или что-то вроде того
[/quote]
дык это же сильно неудобно, при каждом вызове функции обрамлять её #idef'ом.
зачем делать 100 раз то, что можно сделать один раз?
и всех коллег заставлять? (я ведь не один программист на проекте) и каждый вечер просматривать весь проект, проверять, чтоб никто не забыл #idef поставить. и всё равно забудут где-нить поставить и я не замечу.

а про помещение в конструктор... это зачем? это вообще что такое?
вызов пустого конструктора - это ничуть не лучше вызова пустой функции. и конструктору ещё параметры надо прикрутить. я ведь каждый раз разное пишу в лог. и параметр у конструктора будет не один. у меня ведь WRITE_LOG форматную строку поддерживает.
Записан
LifeMaker
Гость
« Ответ #52 : 02-06-2008 20:41 » 

Есть искусственный способ ))

#ifndef __HEADER_SUPER_MACROS
#define __HEADER_SUPER_MACROS
//... код...
#endif // __HEADER_SUPER_MACROS
Сразу видно какой #endif, что закрывает.

Между прочим, Саттер и Александреску рекомендуют использовать именно этот вариант защиты от повторного включения, а не прагмы компиляторов )

конечно, Саттер - глава комитета по стандартизации. кому как не ему защищать стандарт. но я то практик...
(прошу заметить, Саттера, лично я, уважаю)

поторюсь - автор хидера - не я. и то, что автор воспользовался менее удачной конструкцией чем я вылезло боком мне
ps. проект поддерживается только под visual studio. аргументы кроссплатформенности тут не катят
« Последнее редактирование: 02-06-2008 20:43 от LifeMaker » Записан
LifeMaker
Гость
« Ответ #53 : 02-06-2008 20:46 » 

более того, если я буду писать кроссплатформенную библиотеку, я вздохну и напишу #ifndef-#define...
или если волею судьбы мне придётся использовать какой-нибудь слишком нестандартный компилятор.
но если я знаю, что проект никогда не потребует такого, это глупо
Записан
Scorp__)
Молодой специалист

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

« Ответ #54 : 03-06-2008 09:25 » 

Ну у меня ситуация такая, что я не могу быть уверен, что мне не скажут завтра: "а давай-ка то же самое, но под QNX". То есть любое приложение и библиотека должны быть как можно более дружествены к другим компиляторам и платформам )
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
LifeMaker
Гость
« Ответ #55 : 03-06-2008 16:39 » 

Scorp__),
Ну у меня ситуация такая, что я не могу быть уверен, что мне не скажут завтра: "а давай-ка то же самое, но под QNX". То есть любое приложение и библиотека должны быть как можно более дружествены к другим компиляторам и платформам )
Ну если ситуация действительно такая, то наверно так правильно.
Но что-то мне подсказывает, что чаще всего дела обстоят не так...

а что ты пишешь? (если не секрет...)
Записан
Scorp__)
Молодой специалист

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

« Ответ #56 : 03-06-2008 17:09 » 

Блин, даже не знаю как написать ) В основном, это небольшие программки для тестов различных комплексов, для замеров времени выполнения это работа на оборонку и комплексы там сейчас активно переводятся с встраиваемых версий винды на qnx и linux. Но инерция большая, поэтому пока все же пишем под винду.
Да и другие заказы, которые делаю... не раз звучало, что потом может быть придется сделать такое же под Linux, правда пока еще не приходилось ))
Записан

- А Вы сами-то верите в привидения?
- Конечно, нет, - ответил лектор и медленно растаял в воздухе.
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #57 : 04-06-2008 09:57 » 

Scorp__),
Цитата
Есть искусственный способ ))

Код:
#ifndef __HEADER_SUPER_MACROS
#define __HEADER_SUPER_MACROS
//... код...
#endif // __HEADER_SUPER_MACROS
Сразу видно какой #endif, что закрывает.

Между прочим, Саттер и Александреску рекомендуют использовать именно этот вариант защиты от повторного включения, а не прагмы компиляторов )
Это и имелось ввиду.

LifeMaker твой пример с больши хеадером не совсем корректный с ммм практической точкой зрения, если так можно выразиться. Я могу и одну функцию я на 15 старниц написать, а потом попросить кого-то в этом разобраться. Если грамотно писать (это безусловно идеал, но в одной команде он достижим) то классы будут короткие, закрывающий endif содержит комет к чему он относится (я когда еще писал, так у меня просто макрос в студии был, который получал на вход имя неймспейса + класса, а создавал он примерно следующее
Код:
#ifndef __ИМЯНЕЙМСПЕЙСА_ИМЯКЛАССА_H__
#define __ИМЯНЕЙМСПЕЙСА_ИМЯКЛАССА_H__

namespace ИМЯНЕЙМСПЕЙСА
{
class ИМЯКЛАССА
{
public:
ИМЯКЛАССА();
~ИМЯКЛАССА();
};
};

#endif // __ИМЯНЕЙМСПЕЙСА_ИМЯКЛАССА_H__
и вообще не испытывал проблем со временем объявления нового класса, поскольку макрос отрабатывает менее пол секунды) и внутри черезчур много idef (а зачем они? да еще и в таком количестве?)
Записан

С уважением Lapulya
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #58 : 04-06-2008 10:13 » 

LifeMaker,
Цитата
дык это же сильно неудобно, при каждом вызове функции обрамлять её #idef'ом.
зачем делать 100 раз то, что можно сделать один раз?
и всех коллег заставлять? (я ведь не один программист на проекте) и каждый вечер просматривать весь проект, проверять, чтоб никто не забыл #idef поставить. и всё равно забудут где-нить поставить и я не замечу.

вот для этого и это все обернуто в функцию (точнее конструктор), да ее вызов и создание объекта на стеке надо будет стерпеть (потеря производительности на лицо, но если это не критично). Ну а параметры вычисляй уже внутри ifdef (если это не возможно, то и макрос тебя не спасет от их вычислений)

В класс лучше оборачивать чем просто в функцию много потенциальных бонусов при минимуме затрат
Записан

С уважением Lapulya
LifeMaker
Гость
« Ответ #59 : 04-06-2008 19:26 » 

LifeMaker твой пример с больши хеадером не совсем корректный с ммм практической точкой зрения, если так можно выразиться. Я могу и одну функцию я на 15 старниц написать, а потом попросить кого-то в этом разобраться. Если грамотно писать (это безусловно идеал, но в одной команде он достижим) то классы будут короткие, закрывающий endif содержит комет к чему он относится
...
и внутри черезчур много idef (а зачем они? да еще и в таком количестве?)
ну здесь ситуация такая...
хидер на самом деле писался на в нашей команде, это библиотечный хидер, из игрового движка (PopCap framework). Движок кстати, на мой взгляд очень хороший... и то, что там применялась такая конструкция ещё не значит, это кривой код, что писали его неквалифицированные программисты.
Такая структура хидера там действительно нужна. Выглядит это так...
Код:
#ifndef __HEADER_MACROS__
#define __HEADER_MACROS__
// обяъявление классов, которое должно быть только один раз
#endif

#ifdef USING_FEATURE_FLAG

#define FEATURE_ONE feature_one_call()
#define FEATURE_TWO(params) feature_two_call(params)
//...

#else

#define FEATURE_ONE
#define FEATURE_TWO(params)
//...

#endif

в результате такой структуры можно включать этот хидер в разные файлы, предваряя инклуд макросом USING_FEATURE_FLAG, чтобы включить функциональность, либо не предваряя, чтобы выключить. можно даже в один файл несколько раз инклудить попеременно включая или выключая функционал.

хотя я бы реализовал это по другому. вот так...
Код:
//*************************************************************
//header1.h:
//*************************************************************
#pragma once
// обяъявление классов, которое должно быть только один раз



//*************************************************************
//header2.h:
//*************************************************************
#include "header1.h"

#ifdef USING_FEATURE_FLAG

#define FEATURE_ONE feature_one_call()
#define FEATURE_TWO(params) feature_two_call(params)
//...

#else

#define FEATURE_ONE
#define FEATURE_TWO(params)
//...

#endif

и ещё header1.h я бы подкинул в pch. и всё было бы здорово...
Записан
LifeMaker
Гость
« Ответ #60 : 04-06-2008 20:28 » 

LifeMaker,
Цитата
дык это же сильно неудобно, при каждом вызове функции обрамлять её #idef'ом.
зачем делать 100 раз то, что можно сделать один раз?
и всех коллег заставлять? (я ведь не один программист на проекте) и каждый вечер просматривать весь проект, проверять, чтоб никто не забыл #idef поставить. и всё равно забудут где-нить поставить и я не замечу.

вот для этого и это все обернуто в функцию (точнее конструктор), да ее вызов и создание объекта на стеке надо будет стерпеть (потеря производительности на лицо, но если это не критично). Ну а параметры вычисляй уже внутри ifdef (если это не возможно, то и макрос тебя не спасет от их вычислений)

В класс лучше оборачивать чем просто в функцию много потенциальных бонусов при минимуме затрат
я смотрю мы немного недопонимаем друг друга... давай лучше я приведу свой код и объяню, почему я использую макрос и ничто другое.
задача написать вспомогательное нечто, позволяющее легко, не заморачиваясь выводить в уже открытый стандартный FILE* некую форматную строку, возможно не только в файл, но и в Debug Output Visual Studio, TTY игровую консоль, куда угодно в общем-то...
иметь возможность отключить всё это не имея при этом оверхеда (это игровое приложение), в Release-билде каждый FPS на счету.
я могу поместить WRITE_LOG в цикл рендера, там даже вызов пустой функции или пустой конструир объекта с парой параметров может очень сильно подпортить жизнь...
вот так:
Код:
WRITE_LOG("ptr is NULL");
WRITE_LOG("File '%s' not found.",filename.c_str());
WRITE_LOG("Players scores: '%d'.",mPlayerScores);
WRITE_LOG("Matrix value is: %f %f %f %f - %f %f %f %f - %f %f %f %f - %f %f %f %f",mtx[0][0],mtx[0][1],mtx[0][2],mtx[0][3],
mtx[1][0],mtx[1][1],mtx[1][2],mtx[1][3],mtx[2][0],mtx[2][1],mtx[2][2],mtx[2][3],mtx[3][0],mtx[3][1],mtx[3][2],mtx[3][3],);

WRITE_LOG("Player2 health: %f", gGameDataBase->FindPlayerNode("Player2")->GetHealth());

// реализация примерно так WRITE_LOG

#ifdef NDEBUG

#define WRITE_LOG(...)

#else

#ifdef WIN32

#define WRITE_LOG(...) { \
    fprintf(gLogFile,__VA_ARGS__);fprintf(gLogFile,"\n"); \
    char buf[512]; sprintf(buf,__VA_ARGS__); OutputDebugString("buf"); OutputDebugString("\n"); \
}

#endif

#ifdef PS3

#define WRITE_LOG(...) { \
    fprintf(gLogFile,__VA_ARGS__);fprintf(gLogFile,"\n"); \
    PSSG_PRINTF(__VA_ARGS__); PSSG_PRINTF("\n"); \
}

#endif

#endif
при таком подходе в релиз-билде не остаётся ни вызова пустой функции, ни вычисления параметров для формирования строки (как видно из примера - это может быть много параметров или вызовы тяжелых функций поиска и т.п.)

отдельный момент, ради которого используется макрос: проверка GCC компилятором корректности форматной строки.
т.е. вот что он говорит на вот таком коде:
Код:
1: // test.cpp
2: #include <stdio.h>
3: int main()
4: {
5: float f;
6: int i;
7: printf("%d %f",f,i);
8: return 0;
9: }

test.cpp: In function `int main()':
test.cpp:7: warning: int format, double arg (arg 2)
test.cpp:7: warning: double format, different type arg (arg 3)
полезная подсказка чаще всего программист ошибается вот так
Код:
std::string str;
printf("%s",str); //плохо
printf("%s",str.c_str()); //надо было так, все об этом знают, но часто забывают, а вылазит только в рантайме...
так вот, к чему это я... вариант с функцией выглядит примерно так...
Код:
void WRITE_LOG(const char* fmt, ...) 
{
#ifndef NDEBUG
    va_list argList;
    va_start(argList, fmt);
    char buffer[bufSize];
    vsnprintf(buffer, bufSize, fmt, argPtr);
    va_end(argList);
    OutputDebugString(buffer);
    OutputDebugString("\n");
#endif
}
в итоге GCC говорит что-то вроде warning: Format string is not literal. Unable to check parameters.
итого, мы потеряли ценную информацию от компилятора. в случае с макросом вся информация сохраняется, как буд-то мы передали параметры непосредственно в printf (что мы собственно и сделали). и warning уже выручал меня раза три, и коллег уже выручал, хотя WRITE_LOG'у этому всего неделя примерно... и выручит, я думаю, ещё не раз
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #61 : 30-09-2009 10:44 » 

Код:
#define m(a,b,c) a+b+c

int i=m(1,,,,2,,,3,);

это компилируется ))) А почему
Записан

Джон
просто
Администратор

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

« Ответ #62 : 30-09-2009 11:25 » 

Опять олифишь? Ага

warning C4002: too many actual parameters for macro 'm'
error C2105: '++' needs l-value
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #63 : 30-09-2009 11:34 » 

это в VC6 было, вернее не совсем прям так запущено, а двойная запятая была ) Прокатывает
Записан

Джон
просто
Администратор

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

« Ответ #64 : 30-09-2009 12:30 » 

Лёш, что значит двойная запятая? Какая разница?

Ты поставь себя на место компилятора:

из твоего выражения получается так
i = 1++;

остальные параметры значения не имеют, но первые три затребованные должны присутствовать. А так ты и получаешь ошибку: C2105: '++' needs l-value.

Если например ты возьмёшь вот такой вариант:
int i=m(1,2,3,4,5,6,,,,,,7,,,,,,,);

или даже такой

int i=m(1,2,3,4,5,"hallo",new CEdit());

то, кроме предупреждения о превышении числа параметров, всё будет в порядке. Остальные параметры нигде не фигурируют поэтому будут проигнорированы.

Но обязательные должны присутствовать.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #65 : 01-10-2009 03:22 » 

в том и дело, что в 6-й подряд идущие запятые (даже разделённые переводом строки) в параметрах воспринимаются как одна запятая
Записан

Джон
просто
Администратор

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

« Ответ #66 : 01-10-2009 06:32 » 

Покажи точно, какая у тебя строка компилится в шохе.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #67 : 01-10-2009 06:40 » 

так я показал
Код:
#define m(a,b,c) a+b+c

int i=m(1,,,,2,,,3,);


и не просто компилится, но ещё и выполняется правильно
Записан

Джон
просто
Администратор

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

« Ответ #68 : 01-10-2009 07:21 » 

Я вот про что:

вернее не совсем прям так запущено, а двойная запятая была

зы В любом случае так лучше не делать, как минимум в 2003 уже не прокатит.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
lapulya
Молодой специалист

ru
Offline Offline

« Ответ #69 : 07-12-2009 15:38 » 

LifeMaker, хехехе... или гибкость или скорость, от теории к практике путь тернист.

Если пишется приложение реального времени, то конечно, надо дважды подумать о частых вызовах функций, которые в релизе не нужны. Коли игрушка пишется, то макросы рулят (во исходниках фланкера, фрогфута и локона их много), но даже в таких приложениях есть места где не особенно нужна скорость, меню, диалоги и т.д., т.е. когда ты не в кокпите жмешь на гашетку, а в редакторе миссий и т.д. Вот тут то и можно уменьшить количество дефайнов.

Итого, если это не модули ПО, от которых требуется выжать максимум из железки по какому-то показателю,  а "гражданское" приложение, то макросы в утиль. Если это "боевой" слой, то какие нах обертки и т.д. - дефайн (если он оправдан и нужен) рулеззз.
Записан

С уважением Lapulya
Алексей++
глобальный и пушистый
Глобальный модератор

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


« Ответ #70 : 08-12-2009 04:02 » 

lapulya, копил обиду полтора года ? ))  С возвращением, кстати Улыбаюсь
Записан

lapulya
Молодой специалист

ru
Offline Offline

« Ответ #71 : 28-12-2009 12:17 » 

Угу, шучу... А где заяц? Синий такой...
Записан

С уважением Lapulya
RXL
Технический
Администратор

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

WWW
« Ответ #72 : 28-12-2009 13:45 » 

Пробегает временами. Чаще по аськам.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: 1 2 3 [Все]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines