4

I tried to print the line number of the current code by using:

#include <stdio.h>

void err (char *msg)
{
    printf ("%s : %d" , msg , __LINE__);
}

int main ( int argc , char **argv )
{
    ERR ("fail..");
    return 0;
}

But i always get the wrong line number , it should be 10 instead of 5 , how can i fix this ?

Also i tried to use some macro:

#define ERR (msg) do { printf ("%s : %d\n" , msg , __LINE__); } while (0)

and result in error: msg not declared

daisy
  • 22,498
  • 29
  • 129
  • 265

4 Answers4

10

__LINE__ will give you the line on which it appears, which is always line 5.

To make this work, you will need to pass in __LINE__ as a separate parameter.

#include <stdio.h>

void err (char *msg, int line)
{
    printf ("%s : %d" , msg , line);
}

int main ( int argc , char **argv )
{
    err("fail..", __LINE__);
    return 0;
}

An even better way to do this would be to define the invocation of such method as a macro, like so:

#define PRINTERR(msg) err((msg), __LINE__)
Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320
8
#define ERR(msg) printf("%s : %d", (msg), __LINE__)

Should do the trick.

You do not need the function!

Kevin Vermeer
  • 2,736
  • 2
  • 27
  • 38
Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • This is the problem with macros; once you add even a small taste of them to you program, they start to infect everything. – T.E.D. Oct 28 '11 at 12:41
  • 1
    Maybe but this particular task cannot be accomplished without macros. – John Dibling Oct 28 '11 at 13:10
  • 1
    don't put a semicolon inside a macro, otherwise you will get problems when you place it in some `if/else` condition. – Jens Gustedt Oct 28 '11 at 13:17
  • Oops - a typo. BTW - Should always put stuff after `if` in braces. Saves a lot of grief when people add an extra line of code an expect it to work. – Ed Heal Oct 28 '11 at 13:19
  • 1
    @JohnDibling - Right, but only because `__LINE__` is a macro. Once you try to generalize its use, you have to use more macros. If you want to generalize the use of those macro "routines", you'll need **more** macros. So use of the `__LINE__` macro slowly infects your whole program with macros. – T.E.D. Nov 01 '11 at 14:48
  • @T.E.D.: I'm not sure I get your point. Using a device such as [this](http://stackoverflow.com/questions/4196431/passing-the-caller-file-line-to-a-function-without-using-macro/4196475#4196475) to implement logging with filename & line numbers doesn't "infect" your code with macros. It simply uses the best tool for the job where it's needed. Isn't that a good thing? – John Dibling Nov 03 '11 at 14:13
6

__LINE__ gets the current line, meaning the line that it was called on. You need to pass it as a parameter:

ERR ("fail..", __LINE__);

Otherwise it will always be the line inside your error function, 5 in your example. Change your function to accept an int type for the __LINE__ macro.

I would use the macro that @Ed Heal answered with. Also, the reason you are getting "msg not declared" is that variables in macros need to be enclosed in parentheses (i.e. (msg)). because there is a space between the macro's name and the parenthesis that starts the parameter list.

Evan Mulawski
  • 54,662
  • 15
  • 117
  • 144
  • i think it's actually i put a space between `ERR` and '(msg)' , because this one works: `#define ERR(msg) printf ("%s : %d\n" , msg , __LINE__)` – daisy Oct 28 '11 at 12:54
  • No, you don't have to enclose parameters in parentheses. Macro replacement is just textual replacement. – Jens Gustedt Oct 28 '11 at 13:18
  • 2
    It's a good idea to put enclose msg within parentheses because msg could be an expression. Not sure if it's necessary in this case but it's a good rule of thumb. – onemasse Oct 28 '11 at 13:25
0

You can make ERR a macro:

#define ERR(msg) fprintf(stderr, "ERROR on line %d: %s\n", __LINE__, (msg))
hochl
  • 12,524
  • 10
  • 53
  • 87