Какое из худших реальных злоупотреблений макросами / препроцессором вы когда-либо встречали (пожалуйста, не придумывайте ответы IOCCC * хаха *)?
Пожалуйста, добавьте короткий фрагмент или историю, если это действительно интересно. Цель состоит в том, чтобы научить чему-то, вместо того, чтобы всегда говорить людям «никогда не используйте макросы».
ps: я использовал макросы раньше ... но обычно я в конечном итоге избавляюсь от них, когда у меня есть "реальное" решение (даже если реальное решение встроено, поэтому оно становится похожим на макрос).
Бонус: приведите пример, где макрос был действительно лучше, чем не-макро решение.
Смежный вопрос: когда полезны макросы C ++?
c++
c
macros
preprocessor
Trevor Boyd Smith
источник
источник
Ответы:
По памяти это выглядело примерно так:
Да, верно, никаких закрывающих скобок в любой из функций. Подсветка синтаксиса была беспорядочной, поэтому он использовал vi для редактирования (не vim, у него есть подсветка синтаксиса!)
Он был русским программистом, который в основном работал на ассемблере. Он был фанатичен по поводу сохранения как можно большего количества байтов, потому что ранее он работал на системах с очень ограниченной памятью. «Это было для спутника. Лишь очень мало байтов, поэтому мы используем каждый байт для многих вещей». (суетливость, повторное использование байтов машинных инструкций для их числовых значений) Когда я попытался выяснить, какие типы спутников, я смог получить только «Орбитальный спутник. Для выведения на орбиту».
У него было еще две причуды: выпуклое зеркало, установленное над его монитором «Для того, чтобы узнать, кто смотрит», и случайный внезапный выход из кресла, чтобы сделать десять отжиманий. Последний объяснил это как «Компилятор обнаружил ошибку в коде. Это наказание».
источник
Мой худший
Я потратил два дня своей жизни на отслеживание некоторых многопоточных проблем с пересчетом COM, потому что какой-то идиот поместил это в заголовочный файл. Я не буду упоминать компанию, в которой я работал в то время.
Мораль этой истории? Если вы чего-то не понимаете, прочитайте документацию и узнайте об этом. Не просто заставьте это уйти.
источник
источник
for (;;)
идиому, иначе я бы сразу добавил этот макрос в мой код.(defmacro ever ())
а затем(require 'cl (ever))
Задача: может ли кто-нибудь сделать это с меньшим количеством определений и структур? ;-)
источник
public
иstatic as nothing,
void` какint
, иmain(x)
какmain()
, такpublic static void main(String[] args)
превращается вint main()
. ЗатемSystem
превращается вS s;s
, то естьSystem.out.println("Hello World!");
превращается в то,S s; s.out.println("Hello World!");
что вызываетprintln
функцию вF
структуре вS
структуре.источник
class
ключевым словом и первым модификатором доступа.#define class struct #define protected public
Это была шутка, на которой кто-то был
источник
Отвратительный
Серьезно, если вы хотите кодировать на Pascal, купите компилятор Pascal, не разрушайте прекрасный язык C.
источник
«Архитектор», очень скромный парень, вы знаете тип, имел следующее:
потому что он любил печатать быстро. Раньше мозговой хирург любил кричать на людей, которые умнее его (а это было почти все), и угрожать использовать на них свой черный пояс.
источник
killall rn
?Реальный мир? MSVC имеет макросы в minmax.h, вызываемые
max
иmin
, которые вызывают ошибку компилятора каждый раз, когда я собираюсь использовать стандартнуюstd::numeric_limits<T>::max()
функцию.источник
Сочетание синтаксиса Паскаля и французских ключевых слов:
источник
У Раймонда Чена очень хорошие высказывания против использования макросов управления потоком . Его лучший пример - прямо из исходного кода оболочки Bourne:
источник
if
...else
...elif
...fi
иcase
...esac
раньше (на том языке, который Борн изобрел для sh), ноloop
...pool
это настоящая жемчужина.Я хотел бы представить на конкурс камень под названием chaos-pp , который реализует функциональный язык с помощью макросов препроцессора.
Одним из примеров является вычисление 500-го числа Фибоначчи полностью препроцессором:
Исходный код перед препроцессором выглядит так:
При предварительной обработке файла мы получаем следующий результат (после довольно долгого ожидания):
источник
Непосредственно из Qt:
Действительно приятно взаимодействовать с другими библиотеками, такими как boost :: сигналов ... В качестве примера, в Qt есть много других, которые создают забавно выглядящий код, такой как:
И это C ++ ... но вдруг:
Больше не действителен C ++.
источник
В Windows.h много функций, которые злоупотребляют макросами.
MrValdez раздражен макросом GetObject, найденным в Windows.h
Макрос GetObject изменяет функцию GetObject () на GetObjectA () или GetObjectW () (в зависимости от того, скомпилирована ли сборка не в Юникоде и Юникоде соответственно)
MrValdez ненавидит необходимость делать перед строкой функции GetObject
Альтернативой является изменение имени функции на что-то другое, например, GetGameObject ().
jdkoftinoff в комментариях прибил это: проблема в том, что все функции Windows API являются макросами.
Адам Розенфилд отметил, что проблемы могут быть исправлены путем определения NOGDI, WIN32_LEAN_AND_MEAN, NOMINMAX и т. Д. Перед включением windows.h для устранения проблем.
источник
это просто так зло. Он случайный, что означает, что он все время срабатывает в разных местах, он изменяет оператор return, в котором обычно есть какой-то код, который может сам по себе потерпеть неудачу, он меняет невинно выглядящее ключевое слово, над которым вы никогда не будете подозревать, и использует исключение из стандартного пространства, так что вы не будете пытаться искать в своих источниках, чтобы найти его источник. Просто великолепно.
источник
Мы с коллегой нашли эти два драгоценных камня в нашем коде для потоковой передачи объектов. Эти макросы были созданы в КАЖДОМ ОДНОМ файле класса, который выполнял потоковую передачу. Мало того, что этот отвратительный код извергался по всей нашей кодовой базе, когда мы обратились к первоначальному автору по этому поводу, он написал 7-страничную статью в нашей внутренней вики, защищающую это как единственный возможный способ выполнить то, что он пытался сделать здесь.
Излишне говорить, что с тех пор он был переработан и больше не используется в нашей кодовой базе.
Не отбрасывайте выделенные ключевые слова. Это ВСЕ макрос
Обновление (17 декабря 2009 г.):
Больше хороших новостей об этом отвратительном авторе макросов. По состоянию на август сотрудник, ответственный за это чудовище, был уволен.
источник
Я сделал следующее сам, и я думаю, что чему-то научился.
Примерно в 1992 году я написал небольшой переводчик Lisp. Это не было реализовано в обычном C, но в интерпретируемом C-подобном языке. Этот C-подобный язык использовал стандартный препроцессор C, хотя.
Разумеется, интерпретатор Lisp содержал функции car , которые используются в Lisp для возврата первого элемента в списке, и cdr , который возвращает остальную часть списка. Они были реализованы так:
(Данные были сохранены в массивах, поскольку не было структур. CONS_OFFSET - это константа 1000.)
car и cdr часто используются в Лиспе и являются короткими, и поскольку вызовы функций не были очень быстрыми в языке реализации, я оптимизировал свой код, реализовав эти две функции Лиспа в виде макросов:
CHECK_CONS проверяет, что его аргумент на самом деле является списком, и поскольку этот аргумент также часто используется в интерпретаторе и является коротким, я написал его тоже как макрос:
IS_CONS и LISP_ERROR также часто использовались, поэтому я тоже превратил их в макросы:
Кажется разумным?
Но тогда почему вся система рухнула на этой строке:
Я долго работал над поиском проблемы, пока, наконец, не проверил, к чему эта короткая строка была расширена препроцессором. Она была расширена до строки из 31370 символов, которую я здесь разделил на строки (502 из них) для ясности:
источник
I optimized my code by implementing those [..] functions as macros
- знаменитые последние слова ...Однажды мне пришлось портировать приложение C с unix на windows, специфическая природа которого останется безымянной, чтобы защитить виновных. Парень, который написал это, был профессором, не привыкшим писать производственный код, и явно пришел к Си с какого-то другого языка. Бывает и так, что английский не был его родным языком, хотя в стране, из которой он приехал, большинство людей говорят на нем довольно хорошо.
Его приложение интенсивно использовало препроцессор для преобразования языка Си в формат, который он мог лучше понять. Но макросы, которые он использовал чаще всего, были определены в заголовочном файле с именем «Thing.h» (серьезно), который включал следующее:
... который он затем использовал, чтобы написать чудовища, подобные следующим:
Весь проект (~ 60 000 LOC) был написан в похожем стиле - марко ад, странные имена, древнеанглийский жаргон и т. Д. К счастью, мы смогли выбросить код, так как я нашел библиотеку OSS, которая выполняла тот же алгоритм десятки раз быстрее.
(Я скопировал и отредактировал этот ответ, который я изначально сделал на этот вопрос ).
источник
Худшее, с чем я когда-либо сталкивался, было в продукте, содержащем набор исполняемых файлов, где назначенный технический лидер не определил библиотеки.
Вместо этого у него были наборы файлов, которые использовались в нескольких папках Visual Source Safe. Затем он понял, что они должны вести себя немного по-разному для каждого приложения.
Есть несколько шагов рефакторинга, которые вы можете применить здесь.
Вместо этого он использовал #ifdefs
источник
Использование препроцессора LINE для генерации уникального идентификатора для сообщений, передаваемых по сети:
Это пример, где макрос действительно был лучше, чем немароксальное решение:
В классах решений, не относящихся к макросам, функции и переменные должны быть собраны, чтобы отслеживать, какой идентификатор сообщения. Разработчик может усложнить или не усложнить отслеживание идентификатора сообщения, тогда как его легче читать и отлаживать.
Кроме того, проще добавлять новые сообщения, просто добавив сообщение в источник.
Недостатком этой ситуации является то, что файл должен быть включен во весь код, который использует сообщения. Время компиляции будет увеличиваться всякий раз, когда сообщение редактируется.
источник
Один довольно плохой пример:
Это позволяет структуре C, содержащей переменную-член, вызываемую
class
для обработки компилятором C ++. Есть два заголовка с этой конструкцией в нем; один из них также содержит '#undef class' в конце, а другой нет.источник
@class
вместоclass
.За один год Международного конкурса кодирования с запутанным кодом была запись, где вся программа была:
P
С условием, что вы можете определить
P
в make-файле любую программу, какую захотите.Насколько я помню, он выиграл в одной из категорий, и в следующем году появилось правило, запрещающее такой стиль входа.
(Изменить: через шесть месяцев или что-то ... Я уверен, что "Нет IOCCC" не было в основном вопрос, когда я написал это ...)
источник
Мне было скучно однажды, и я играл с блоками в Objective-C ...
позволяет "интересные" вещи, такие как:
(некоторые определения функций и классов не показаны для краткости)
источник
Худшее, что я видел, было неиспользованием :-)
Кто-то написал функцию strcpy (я думаю, что это было ... более 10 лет назад) внутри метода (потому что он не хотел накладных расходов на вызов strcpy ... sigh).
Они поняли, что для японских символов это не сработает, поэтому в начале добавили «если», чтобы сделать ASCII или Unicode. На тот момент код был длиной около экрана ... вероятно, это нарушало целостность кэша и стирало его предполагаемую экономию для встраивания кода.
Код был идентичным, за исключением типов (поэтому следовало использовать макрос).
Конечно, написанная ими strcpy была намного намного медленнее, чем вручную настроенный ассемблер, который был в стандартной библиотеке ...
Конечно, если бы они сделали все это как макрос, его можно было бы заменить вызовом strcpy ...
Конечно, я ухожу из компании (не напрямую из-за этого ...)
источник
The code was identical save for the types (so should have used a macro).
Нет, он должен был использовать шаблон.Обязательный
и
Кто знал?
источник
Человек, который сделал это, объяснил себя несколько лет спустя - большинство (если не все) библиотечные функции C возвращают 0 как признак того, что все прошло хорошо. Итак, он хотел иметь возможность писать код вроде:
Излишне говорить, что никто в нашей команде (тестер или разработчик) никогда не осмеливался взглянуть на его код снова.
источник
#define FLAG_SUCCESS 0
?Я поддерживаю код с gotos в макросах. Таким образом, функция будет иметь метку в конце, но не будет видимого перехода в коде функции. Что еще хуже, макрос находится в конце других операторов, как правило, за кадром, если вы не прокручиваете горизонтально.
источник
goto
операторы, так и определения целевых меток. Абсолютно волшебство.источник
Одноклассник, который не смог понять правила о магических числах:
#define TWO_HUNDRED_AND_EIGHTY_THREE_POINT_ONE 283.1
источник
ASA - http://www.ingber.com/#ASA
Вы действительно должны загрузить это, чтобы оценить это. Весь рабочий процесс определяется макросами. Это совершенно нечитаемо. Например -
и т. д.
И это только настройка параметров. вся программа такая.
источник