Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.91/46: Рейтинг темы: голосов - 46, средняя оценка - 4.91
ertyuo
0 / 0 / 0
Регистрация: 05.01.2010
Сообщений: 9
#1

Чем же макрос define так плох?

08.01.2010, 03:29. Просмотров 8373. Ответов 115

После прочтения про директиву препроцессора define возник вопрос по поводу применения define, как функции:
C++
1
#define QQ (q) (q^q)
Можно же улучшить читаемость кода, используя вместо функций именно директиву define. Или у данного использования макроса есть подводные камки какие-то? Да и объем кода в разы сократиться, так как для define будет достаточно всего-навсего одной строчки.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.01.2010, 03:29
Ответы с готовыми решениями:

Чем плох make?
Дали написать реферат по make файлам и соответственно указать его минусы, а...

Чем плох std::map?
std::map ?

Чем плох void main?
Встретил мнение, что void main() - не канон и даже плохо. Но статья древняя,...

Чем плох управляемый С++?
Я дико извиняюсь за подобную тему... но дело в том, что мне сегодня задали этот...

Перевести макрос define в функцию
Доброго времени суток. Я тут на днях набросал вот такие макросы для удобства:...

115
niXman
Эксперт С++
3202 / 1451 / 73
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
08.01.2010, 03:53 #2
это макросы препроцессора.
на стадии их "расширения" не производится проверка компилятором. потому, отыскать ошибки, связанные с макросами, крайне сложно.
и вообще, это плохой тон.

а для случая который вы привели, прекрасно подходит функция.
1
Gravity
569 / 563 / 64
Регистрация: 29.01.2009
Сообщений: 1,274
08.01.2010, 03:54 #3
Цитата Сообщение от ertyuo Посмотреть сообщение
Можно же улучшить читаемость кода, используя вместо функций именно директиву define.
Для читабельности нет особой разницы между обычной функцией и макросом. Макросы делают для того, чтобы не создавался кадр стека (как при вызове функции), за счет этого код выполняется несколько быстрее. Но необходимость в макросах отпала с появлением inline-функций, которые есть и в C++ и в C99.
2
ertyuo
0 / 0 / 0
Регистрация: 05.01.2010
Сообщений: 9
08.01.2010, 12:13  [ТС] #4
Спасибо за ответы, про inline не знал... Как-то кроме программных файлов - conio.h не видел его применения, да и в учебниках особенного упоминания...
0
Nick Alte
Эксперт С++
1647 / 1019 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
08.01.2010, 13:54 #5
Цитата Сообщение от niXman Посмотреть сообщение
и вообще, это плохой тон.

Вообще-то макросы - плохой тон как раз из-за этих их неприятных особенностей.
Основные минусы - неудобство в отладке, засорение глобального пространства имён, возможность возникновения всяких неприятных непредвиденных эффектов. Например, в приведённом в открывающем посте примере человек, написавший QQ(7) будет долго и упорно думать над непонятными ошибками. А когда догадается посмотреть результат работы препроцессора, к его неприятному изумлению найдёт на месте QQ(7) текст (q) (q^q)(7). Пробел после QQ, видите ли.
А если он и уберёт пробел, то получит интересные, но неправильные результаты на вызове вроде QQ(5+7). А если кто-то случайно позарится на такое же имя для своей функции, имея такое объявление где-то в своих заголовках, получит массу интересных ощущений при попытке разрыть непонятные еггоги.
1
outoftime
║XLR8║
756 / 656 / 211
Регистрация: 25.07.2009
Сообщений: 3,297
Записей в блоге: 5
08.01.2010, 14:04 #6
значит для быстроты:
C++
1
#define FOR(i,a,b) for (int i(a),_b(b); i < _b; ++i)
это плохой тон?
1
Evg
Эксперт CАвтор FAQ
19278 / 7135 / 528
Регистрация: 30.03.2009
Сообщений: 19,976
Записей в блоге: 30
08.01.2010, 14:10 #7
ertyuo, почитай тут http://www.cyberforum.ru/faq/thread55559.html
Конкретно ответ на твой вопрос - разделы 3.3.2 и 3.3.3
0
Nick Alte
Эксперт С++
1647 / 1019 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
08.01.2010, 14:29 #8
outoftime, да, плохой. Точнее говоря, не "плохой тон", а "плохой стиль".
В конце концов, это же программирование, а не ловля блох, тут спешка вообще вредна. А если не устраивает скорость, с которой печатаются буковки, бери денежку и иди на поклон к Владимиру Владимировичу Шахиджаняну - так всяко лучше будет.
0
outoftime
║XLR8║
756 / 656 / 211
Регистрация: 25.07.2009
Сообщений: 3,297
Записей в блоге: 5
08.01.2010, 14:39 #9
Nick Alte, ты о спортивном програмировании слышал?

Добавлено через 4 минуты
ertyuo, в твоем коде сть недочет:
C++
1
#define QQ (q) (q^q)
если я возьму q = 5 - все ок, а если q = a*b+vs.size()-1 - тут у тебя будут проблемы, пиши
C++
1
#define QQ(q) ( (q)  ^ (q) )
0
Nick Alte
Эксперт С++
1647 / 1019 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
08.01.2010, 14:43 #10
outoftime, ради спорта, конечно, можно и плохим стилем пользоваться. Но если собираешься писать программы, которыми реально будут пользоваться люди, лучше приучать себя к хорошему стилю. А уж если собираешься писать достаточно большие и сложные программы, все эти "маленькие спортивные хитрости" лучше забыть как страшный сон.
1
outoftime
║XLR8║
756 / 656 / 211
Регистрация: 25.07.2009
Сообщений: 3,297
Записей в блоге: 5
08.01.2010, 14:48 #11
Nick Alte, "Преждевременная оптимизация - корень всех зол." Д. Кнут
я обычно юзаю два екземпляра кода)
0
odip
Эксперт С++
7161 / 3220 / 76
Регистрация: 17.06.2009
Сообщений: 14,161
08.01.2010, 14:50 #12
Всем кто считает что define и макросы - это плохой тон или стиль.
Откройте стандартные include-файлы для любого компилятора в любой системе !
Вы офигеете от того кол-ва макросов, которое там используется !

А еще есть некоторые случае когда использование макросов повышает читаемость текста
outoftime, в посте #6 привел один из примеров
0
Nick Alte
Эксперт С++
1647 / 1019 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
Завершенные тесты: 1
08.01.2010, 14:53 #13
При всей противоречивости этих высказываний outoftime, оба они имеют одинаково мало отношения к обсуждаемой теме.
odip, это тяжёлое наследие царского режима, которое до сих пор должно быть совместимым с Си. А вообще, я и так офигеваю, когда у меня какой-нибудь метод называется аналогично одной из тысяч функций, определённых в Windows через макросы. Бывают отдельные случаи, плюсы макросов перевешивают минусы, но не так уж и часто. Да и в таких случаях лучше изолировать опасные участки.
0
outoftime
║XLR8║
756 / 656 / 211
Регистрация: 25.07.2009
Сообщений: 3,297
Записей в блоге: 5
08.01.2010, 14:59 #14
Цитата Сообщение от odip Посмотреть сообщение
А еще есть некоторые случае когда использование макросов повышает читаемость текста
с этим согласен, особенно когда надо впихнуть несколько слогаемых, или что-бы не писать find(a.begin(),a.end(),'6')-a.begin() в форе несколько раз, лично я юзаю только для быстроты, но если мне легче расписать (для понимания) тогда расписываю, как по мне, дефайны плохо воспринимаются, но они сами наклёвываются, когда пишешь сто раз одно и тоже..
0
Rififi
2363 / 1056 / 104
Регистрация: 03.05.2009
Сообщений: 2,656
08.01.2010, 15:05 #15
ertyuo,

Можно же улучшить читаемость кода, используя вместо функций именно директиву define.

с развитием алгоритмов оптимизации в компиляторах использование define вместо функций потеряло смысл. а вот проблем огрести можно.

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

я уж и не говорю о классическом случае:

#define MIN(a,b) ((a) < (b) ? (a) : (b))
int i=10, j=20;

MIN(i++, j--);

например с макросом возможна вот такая потенциальная кривизна:
int i = ...
unsigned j = ...;
MIN(i, j);

а со встроенной функцией - будет ошибка компиляции
std::min(i, j);

короче говоря, если ты только точно не знаешь что делаешь - не используй макросы.
0
outoftime
║XLR8║
756 / 656 / 211
Регистрация: 25.07.2009
Сообщений: 3,297
Записей в блоге: 5
08.01.2010, 15:11 #16
не, не хочу стандартную функцию юзать, я из-за того что она не то вернула контест был запорол..
я лучше дефайны юзать буду..
0
LynXzp
1 / 0 / 0
Регистрация: 22.10.2015
Сообщений: 6
22.10.2015, 11:27 #17
Кликните здесь для просмотра всего текста
Немножко старую тему отрыл. Но это вечно и может быть полезно другим. Почитал тут и на хабре, ничего убедительного, кроме
MIN(a++,b++);
За это отдельное спасибо - по моему мнению, пока единственный случай когда макросы действительно сливают воду.
Но вот задумался отдать заказчику программу (представляет собой библиотеку и небольшой пример ее применения, изменятся будет только пример и в большой переростать не будет). Хотелось бы чтобы заказчику, как далекому от программирования человеку былобы проще указывать цвета не в RGB числами, а их человеческими названиями.

Язык С99 (99 потому что определения переменных можно ставить где угодно, а так 89). Задача: программирование микроконтроллеров.

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

Интересует как на счет констант.
C
1
2
3
4
#define clRed 0xff0000
#define clGreen 0x00ff00
........... over9000
WriteText(clRed,"bla-bla")
Просто считается ли это дурным тоном в академическом мире и мире сферического программирования на С/С++?
(В практическом смысле меня уже мало в чем можно переубедить, но не хочу нарушать ничьего чувства прекрасного)

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

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

Кликните здесь для просмотра всего текста
Вообще первый раз вижу что были проблемы из-за того что кто-то не обернул скобочки. Это же в каждом учебнике написано на той же странице что и макросы. ИМНО это не минус. Минус в том что нужно ставить скобочки и их не должен ставит препроцессор по стандарту.

int i = ...
unsigned j = ...;
MIN(i, j);
а со встроенной функцией - будет ошибка компиляции
std::min(i, j);
Ну это только в С++.

засорение глобального пространства имён
Точно так же как и функции. (Функции можно обернуть в класс? Макросы - в файл. #undefine нет смысла использовать - делает макароны из файла)

Макрос в заголовке? Ну вы же не даете на экспорт функции которые не хотите чтобы были импортированными всеми.

И еще ни #inline ни -О3 совершенно не означают что функция будет встроена. По крайней мере для avr-gcc
.

P.S. мой личный (точнее с другом придумали) трюк позволяющий и видеть числа на месте констант в коде и 'никаких чисел в коде'
#define MAX_LENGTH_50 50
А при изменении переименовать. Не оч удобно если во многих файлах используется константа, но какая красота - у меня все константы теперь такие, и никакого копроммиса. (Ну clRed разве что и то это для заказчика)

P.P.S. люблю подшучивать: детям нельзя делить на ноль, секс и использовать goto. Может макросы стоит добавить сюда.
0
sourcerer
22.10.2015, 11:36
  #18

Не по теме:

Цитата Сообщение от Nick Alte Посмотреть сообщение
иди на поклон к Владимиру Владимировичу Шахиджаняну
Отстой. Бесячий тип. У меня рвотный рефлекс на него. Stamina - лучший клавиатурный тренажёр, имхо.

0
ForEveR
В астрале
Эксперт С++
7995 / 4754 / 651
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
22.10.2015, 11:38 #19
Цитата Сообщение от LynXzp Посмотреть сообщение
Точно так же как и функции. (Функции можно обернуть в класс? Макросы - в файл. #undefine нет смысла использовать - делает макароны из файла)
Функции можно обернуть в namespace.
Макросы ради констант в С++ использовать не стоит, либо const переменная, либо enum.
1
sourcerer
Модератор
Эксперт CЭксперт С++
4832 / 2023 / 315
Регистрация: 20.02.2013
Сообщений: 5,427
Записей в блоге: 24
Завершенные тесты: 1
22.10.2015, 11:43 #20
LynXzp, тебе надо дать медаль почётного археолога
2
22.10.2015, 11:43
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
22.10.2015, 11:43

Чем оличается define от const
define A 5; и const a = 5; В первом случае идет замена в предпроцессоре......

#define работает не так, как ожидается
Здравствуйте. Подскажите, пожалуйста, почему в таком случае некорректно...

#define sqr(a) (a)*(a) - зачем так много скобок?
#define sqr(a) ((a)*(a)) такие вопросы: 1) Зачем ((a)*(a)) так много...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru