Какие приложения оператора ## препроцессора и ошибки должны быть рассмотрены? - PullRequest
86 голосов
/ 19 октября 2008

Как упоминалось во многих моих предыдущих вопросах, я работаю через K & R и в настоящее время работаю в препроцессоре. Одна из самых интересных вещей & mdash; что-то, чего я никогда не знал ни в одной из моих предыдущих попыток изучить C & mdash; является ## оператором препроцессора. По данным K & R:

Оператор препроцессора ## обеспечивает способ объединения фактических аргументы при расширении макроса. Если параметр в тексте замены рядом с ##, параметр заменен фактическим аргументом, ## и окружающие пробелы удаляется, и результат повторно сканируется. Например, макрос paste объединяет два аргумента:

#define paste(front, back) front ## back

так paste(name, 1) создает токен name1.

Как и почему кто-то использовал бы это в реальном мире? Каковы практические примеры его использования, и есть ли какие-либо моменты для рассмотрения?

Ответы [ 13 ]

1 голос
/ 20 октября 2008

Основное использование - когда у вас есть соглашение об именах, и вы хотите, чтобы ваш макрос использовал это соглашение об именах. Возможно, у вас есть несколько семейств методов: image_create (), image_activate () и image_release (), а также file_create (), file_activate (), file_release () и mobile_create (), mobile_activate () и mobile_release ().

Вы можете написать макрос для обработки жизненного цикла объекта:

#define LIFECYCLE(name, func) (struct name x = name##_create(); name##_activate(x); func(x); name##_release())

Конечно, своего рода «минимальная версия объектов» - не единственный вид соглашения об именах, к которому это применимо - почти подавляющее большинство соглашений об именах используют общую подстроку для формирования имен. Это могут быть имена функций (как указано выше) или имена полей, имена переменных или что-то еще.

1 голос
/ 20 октября 2008

Я использую его для добавления пользовательских префиксов в переменные, определенные макросами. Так что-то вроде:

UNITTEST(test_name)

расширяется до:

void __testframework_test_name ()
0 голосов
/ 20 октября 2008

Это очень полезно для регистрации. Вы можете сделать:

#define LOG(msg) log_msg(__function__, ## msg)

Или, если ваш компилятор не поддерживает функцию и func :

#define LOG(msg) log_msg(__file__, __line__, ## msg)

Вышеупомянутые «функции» регистрируют сообщение и показывают, какая именно функция зарегистрировала сообщение.

Мой синтаксис C ++ может быть не совсем правильным.

...