1

I want to write an function that will print out error messages/warnings in my program together with the file & line number. There are these two macros in C:

__FILE__
__LINE__

but there's a problem in my opinion... When I'm writing a function like this:

#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;
}

There are still a lot of useless function calls & trash (the values of __FILE__ and __LINE__ at every call) in the binary file, even if I undefine DEBUG for the release build. So how can I accomplish this more elegant? I want something like this:

#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;
}

But not writing #ifdef DEBUG and #endif before and after every function call - that would be too huge for such an task. And remove every error(AT, "fake error"); call manually isn't really elegant as well...

Any ideas? Maybe inline the function (would not help, wouldn't it)? Some macro or an change of this construct?

5 Answers 5

3

Just turn error into a macro:

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

then, in your functions, write

ERROR(AT, "fake error");

Of course, you could also simplify ERROR and get rid of AT as the first parameter, directly specifying this information in the macro definition.

Sign up to request clarification or add additional context in comments.

Comments

2

Wrapping error() in a macro is indeed the right way to go - I'd write it like so:

#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

Comments

2

you can use this variadic macro to mimic printf which writes file and line no with desired out put.

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

edit : modified eprintf from the suggestions of jcsalomon

3 Comments

This is for C99 or C++0x only, and would be better defined #define eprintf(...) do {fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); fprintf(stderr, __VA_ARGS__)} while(0); note the statements wrapped in a do{…}while(0), and (more to the point) fprintf(stderr, __VA_ARGS__) which lets you pass a raw string without extra argument.
ya i know, tats why i wrote it will be similar to above statement.
Just tried it and there's a missing ; after __VA_ARGS__) otherwise it's a really nice solution!
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;
}

Comments

1

replace error with #define

something like:

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

You could also move AT into error instead of passing it each time

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.