Nano Hash - криптовалюты, майнинг, программирование

Заставить макрос C заменить себя вызовом функции в результате?

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

Я пытался:

/* Declare function. */
void logmsg(const char *fmt, ...) __attribute__((format(printf, 1, 2)));

/* Declare macro (with the same name). */
#define logmsg(fmt, ...) \
        logmsg(fmt, ##__VA_ARGS__)

Однако это не удается с ошибкой компиляции:

In file included from util.c:53:
../lib/util.h:296:13: error: expected identifier or ‘(’ before ‘do’
  296 |             do { if (1) (logmsg(fmt, ##__VA_ARGS__)); } while (0)
      |             ^~
util.c:248:6: note: in expansion of macro ‘logmsg’
  248 | void logmsg(const char *fmt, ...)
      |      ^~~~~~
../lib/util.h:296:59: error: expected identifier or ‘(’ before ‘while’
  296 |             do { if (1) (logmsg(fmt, ##__VA_ARGS__)); } while (0)
      |                                                           ^~~~~
util.c:248:6: note: in expansion of macro ‘logmsg’
  248 | void logmsg(const char *fmt, ...)

Как я могу достичь своей цели?

ИЗМЕНИТЬ:

Я решил проблему с помощью косвенная ссылка идентификатора макроса на самого себя, например:

void logmsg(const char *fmt, ...) __attribute__((format(printf, 1, 2)));

#define log_impl(specarg, fmt, ...) \
            logmsg(fmt,##__VA_ARGS__)

#define logmsg(fmt, ...) \
            log_impl(msg,fmt,##__VA_ARGS__)

Аргумент msg для log_impl() скорее не нужен, но я спрятал код и не могу проверить его, чтобы быть уверенным.


  • Я не уверен, какое это имеет отношение к неявному объявлению, которое в любом случае было незаконным с C99. 13.01.2021
  • Я думаю, что ваше первоначальное намерение ошибочно. Если вы забудете включить заголовок, лучшим результатом будет то, что он вызовет ошибку, поэтому вы можете исправить это, добавив #include. 13.01.2021
  • Вызовите функцию по-другому и свяжите один объект без включения макроса, но с именем макроса, который вызывает функцию с другим именем. Не очень приятно. 13.01.2021
  • Невозможно воспроизвести. 13.01.2021
  • Можете ли вы опубликовать минимально воспроизводимый пример? Я не понимаю, что именно находится в вашем заголовке, что в вашем исходном файле и где возникает ошибка. 13.01.2021
  • @Barmar: я часто выполняю временную отладку нескольких файлов, добавление #includes в таком сценарии утомительно… 13.01.2021
  • Также обратите внимание, что вызов функции с многоточием (, ...) в списке аргументов без прототипа в области действия является неопределенным поведением. C11 §6.5.2.2 Вызовы функций: Если функция определена с типом, включающим прототип, и либо прототип заканчивается многоточием (, ...), либо типы аргументов после повышения несовместимы с типами параметров, поведение не определено.. Вам нужно избегать неопределенного поведения. Это относится к C90, а также к C99, C11, C18. 13.01.2021

Ответы:


1

Вам нужно остерегаться расширения макроса logmsg в вашем объявлении(ях) функции logmsg и в ее определении.

То, что должно работать независимо от вашего порядка определения макроса и вашего реального кода C, относящегося к функции logmsg, всегда использует круглые скобки вокруг ссылок на функцию logmsg:

void (logmsg)(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
void (logmsg)(const char *fmt, ...)
{
//...
}
12.01.2021

2

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

#undef logmsg
void logmsg(const char *fmt, ...)
{
    ...
12.01.2021
Новые материалы

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

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..


© 2024 nano-hash.ru, Nano Hash - криптовалюты, майнинг, программирование