Почему макрос не может использовать статическую функцию? - PullRequest
0 голосов
/ 03 февраля 2019

Я смотрел на этот проект github logger и пробовал его в своей среде.Я попытался изменить функцию log_log на static, чтобы она не могла быть вызвана в другом файле и вынудила «пользователей» (меня) использовать только макросы.

Когда я меняю функцию на статическую, я получаю неопределенную ссылку в main, хотя макрос должен ее видеть.Почему это?И есть ли способ сделать это?

#include <stdio.h>
#include <stdarg.h>

#define LOG_VERSION "0.1.0"

typedef void (*log_LockFn)(void *udata, int lock);

enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };

#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)
#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define log_info(...)  log_log(LOG_INFO,  __FILE__, __LINE__, __VA_ARGS__)
#define log_warn(...)  log_log(LOG_WARN,  __FILE__, __LINE__, __VA_ARGS__)
#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)

void log_set_udata(void *udata);
void log_set_lock(log_LockFn fn);
void log_set_fp(FILE *fp);
void log_set_level(int level);
void log_set_quiet(int enable);

void log_log(int level, const char *file, int line, const char *fmt, ...);

Ответы [ 3 ]

0 голосов
/ 03 февраля 2019

Почему макрос не может использовать статическую функцию

Макросы не используют любую функцию.Они просто расширяются до исходного кода или его фрагментов.Исходный код, сгенерированный таким образом, может включать в себя вызовы функций, но он имеет точно такую ​​же семантику, как если бы он появился буквально в файле, а не в результате расширения макроса.

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

0 голосов
/ 03 февраля 2019

Вы получаете ошибку компоновщика 'undefined reference', потому что функция log_log не определена в заголовке;это просто объявлено.(См. Понимание разницы между определением и объявлением переменной ; понятия аналогичны для объявления и определения функций.)

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

Вы не можете делать то, что пытались, не переходячерез искажения, такие как включение исходного файла - не заголовка, а исходного файла - который определяет log_log в коде, который содержит вашу функцию main().Однако вы действительно не хотите этого делать;Вы действительно , действительно , действительно не хотите этого делать.

Пусть лень защитит вас: этогораздо сложнее набрать log_log(CS_POTATOES, "codswallop", -366, "abuse is rampant"), чем log_trace("abuse is rampant"), поэтому люди вряд ли это сделают.И вы всегда можете искать и заменять прямые звонки на log_log, отправляя соответствующие предупреждения всем членам вашей команды, склонным злоупотреблять им.

0 голосов
/ 03 февраля 2019

Препроцессор ничего не понимает в C. Все, что делает препроцессор, - это заменяет любые экземпляры макросов log_*** вызовами log_log.Только после того, как препроцессор завершил выполнение этих подстановок, компилятор вмешивается, чтобы прочитать код, который был изменен препроцессором.

Компилятору все равно, что эти вызовы log_log были введены.в препроцессоре.Все, что он видит, - это ссылка на функцию, которую вы не должны использовать, потому что вы объявили ее static, поэтому она выдает ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...