Cpp: Как понять и / или отладить сложные макросы? - PullRequest
0 голосов
/ 12 января 2019

Я пытаюсь выучить приемы препроцессора, которые мне показались не такими простыми ( Можем ли мы иметь рекурсивные макросы? , Есть ли способ использовать строковое преобразование C ++ для аргументов переменных переменных?, препроцессор C ++ __VA_ARGS__ количество аргументов , трюк с переменным макросом , ...).

Мне известна опция -E, чтобы увидеть результат всего прохода препроцессора, но я хотел бы знать, существуют ли опции или средства для просмотра результата шаг за шагом. Действительно, иногда трудно проследить, что происходит, когда макрос вызывает макрос, вызывающий макрос ... с механизмом отключения контекста, рисования синим цветом ... Короче, мне интересно, является ли своего рода отладчик препроцессора с точками останова и другими инструменты существуют.

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

Ответы [ 3 ]

0 голосов
/ 12 января 2019

Единственный способ увидеть, что не так с вашим макросом, - это добавить опцию, которая сохранит временные файлы после завершения компиляции. Для gcc это -save-temps опция. Вы можете открыть файл .i и развернутые макросы.

Индексаторы IDE (например, Eclipse) не сильно помогут. Они не будут расширять (как указано в других ответах) макросы, пока не произойдет ошибка. enter image description here

0 голосов
/ 12 января 2019

Этот ответ на другой вопрос актуален.

Когда вы делаете странные уловки препроцессора (которые являются законными), полезно попросить компилятор сгенерировать предварительно обработанную форму (например, с помощью gcc -C -E при использовании GCC ) и посмотреть на эту предварительно обработанную форму.

На практике для исходного файла foo.c имеет смысл (иногда) получить предварительно обработанную форму foo.i с gcc -C -E foo.c > foo.i и посмотреть на нее foo.i.

Иногда даже имеет смысл получить это foo.i без информации о строке. Хитрость здесь (удаление информации о строках, содержащейся в строках, начинающихся с #) заключается в следующем:

gcc -C -E foo.c | grep -v '^#' > foo.i

Тогда вы можете indent foo.i и скомпилировать его, например. с gcc -Wall -c foo.i; вы обнаружите места ошибок в предварительно обработанном файле, и вы сможете понять, как вы это получили, и вернуться к своим макросам препроцессора (или их вызовам).

Помните, что препроцессор C в основном представляет собой текстовое преобразование, работающее на уровне файлов. Невозможно макроразвернуть несколько строк в изоляции (поскольку предыдущие строки могли воспроизводиться с #if в сочетании с #define - возможно, в предыдущих #include -d файлах - или опции препроцессора , такие как -DNDEBUG, переданные в gcc или g++). В Linux см. Также feature_test_macros (7)

Известный пример расширения, которое работает по-разному при компиляции с -DNDEBUG или без него, переданного компилятору: assert. Значение assert(i++ > 0) (что очень неправильно для кода) зависит от него и показывает, что макроразложение не может быть выполнено локально (и вы можете представить себе какой-то предыдущий заголовок, имеющий #define NDEBUG 1, даже если, конечно, это плохой вкус).

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

NB. Вам не нужен Eclipse для всего этого, достаточно хороший редактор исходного кода (я предпочитаю emacs , но это дело вкуса): для задачи предварительной обработки вы можете использовать ваш компилятор.

0 голосов
/ 12 января 2019

Да, этот инструмент существует как функция Eclipse IDE . Я думаю, что по умолчанию способ доступа к этой функции - навести курсор на макрос, который вы хотите видеть развернутым (это покажет полное расширение), а затем нажать F2 на клавиатуре (появится всплывающее окно, которое позволяет вам переходить по каждому расширению) .

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

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

...