2011-01-19 2 views
1

Я хочу написать функцию, которая будет печатать сообщения об ошибках/предупреждения в моей программе вместе с файлом & номер строки. Есть эти два макроса в C:Чистая функция вывода отладки?

__FILE__ 
__LINE__ 

но есть проблема, на мой взгляд ... Когда я пишу функцию, как это:

#include <stdio.h> 
#define STRINGIFY(x) #x 
#define TOSTRING(x) STRINGIFY(x) 
#define AT __FILE__ ":" TOSTRING(__LINE__) 
void error(const char *location, const char *msg) 
{ 
#ifdef DEBUG 
    printf("Error at %s: %s\n", location, msg); 
#endif 
} 
int main(int , char**) 
{ 
    error(AT, "fake error"); 
    return 0; 
} 

Есть еще много бесполезные вызовы функций & trash (значения __FILE__ и __LINE__ при каждом вызове) в двоичном файле, даже если я не могу определить DEBUG для сборки релиза. Итак, как я могу сделать это более элегантным? Я хочу что-то вроде этого:

#include <stdio.h> 
#define STRINGIFY(x) #x 
#define TOSTRING(x) STRINGIFY(x) 
#define AT __FILE__ ":" TOSTRING(__LINE__) 
void error(const char *location, const char *msg) 
{ 
    printf("Error at %s: %s\n", location, msg); 
} 
int main(int , char**) 
{ 
#ifdef DEBUG 
    error(AT, "fake error"); 
#endif 
    return 0; 
} 

Но не писать #ifdef DEBUG и #endif до и после каждого вызова функции - это было бы слишком огромно для такой задачи. И удалить каждый звонок error(AT, "fake error"); вручную тоже не очень элегантный ...

Любые идеи? Может быть, встроенная функция (не помогла бы, не так ли?) Какой-то макрос или изменение этой конструкции?

ответ

2

Оберточные error() в макросе действительно правильный путь - я бы написать это так:

#ifdef DEBUG 
static void error(const char *file, long line, const char *msg) 
{ 
    fprintf(stderr, "Error (%s:%ld): %s\n", file, line, msg); 
} 
#define error(msg) (error)(__FILE__, __LINE__, msg) 
#else 
#define error(msg) ((void)0) 
#endif 
3

Просто включите error в макрос:

#ifdef DEBUG 
# define ERROR(l, m) error(l, m) 
#else 
# define ERROR(l, m) 
#endif 

тогда в ваших функциях, напишите

ERROR(AT, "fake error"); 

Конечно, вы могли бы также упростить ОШИБКУ и избавиться от AT в качестве первого параметра, прямо указывая эту информацию в определении макроса.

1
#ifdef DEBUG 
#define ERROR(msg) error(AT, msg) 
#else 
#define ERROR(msg) 
#endif 

int main(int argc, char * argv[]) 
{ 
    ERROR("fake error"); 
    return 0; 
} 
1

заменить ошибку с #define

что-то вроде:

#ifdef DEBUG 
#define error(a,b) printf("Error at %s: %s\n", (a), (b)) 
#else 
#define error(a,b) 
#endif 

Вы также можете переместить AT в заблуждение вместо передачи его каждый раз

2

вы можете использовать этот макрос VARIADIC mimic printf, который пишет файл и строку нет с желаемым выводом.

#define eprintf(...) do {fprintf(stderr, "%s:%d: ", __FILE__, __LINE__);\ 
fprintf(stderr, __VA_ARGS__);} while(0) 

редактировать модифицированный eprintf из предложений jcsalomon

+0

Это для C99 или C++ 0x, и будет лучше определен '#define eprintf (...) do {fprintf (stderr,"% s:% d: ", __FILE__, __LINE__); fprintf (stderr, __VA_ARGS__)} while (0) '; обратите внимание на утверждения, заключенные в 'do {...} while (0)', и (более точно) 'fprintf (stderr, __VA_ARGS __)', который позволяет передавать необработанную строку без дополнительных аргументов. –

+0

ya я знаю, tats, почему я написал, он будет похож на предыдущий оператор. – Rozuur

+0

Просто попробовал, и там отсутствует ';' после '__VA_ARGS __)' иначе это действительно приятное решение! – lfxgroove

Смежные вопросы