tags:

views:

116

answers:

3

Hi, I've a problem , as the following code discribe itself.

1  #include<stdlib.h>
2  #include<stdio.h>
3  void log()
4  {
5         printf("Log [Line:%d]\n",__LINE__);
6  }
7  int main()
8  {
9         log();
10        log();
11 }

The expected result is
Log [Line:9]
Log [Line:10]
But, the fact is
Log [Line:5]
Log [Line:5]

No surprising, LINE has been substituted at the pre-process stage as 5.
My Question is, how to design the log function to get the expected result?
Thanks!

+12  A: 

You need to write a macro:

#define LOG printf("Log [Line:%d]\n",__LINE__)

then use it:

int main() {
    LOG;
    LOG;
}

This works because the macro is expanded at its point of use, giving the __LINE__ macro the correct value.

anon
In the case of C++, you could also use an inline function.
waffleman
@waffleman No you can't - macro expansion (of the `__LINE__` macro) takes place before the compiler sees the code.
anon
An inline function won't work - `__LINE__` is a preprocessor macro so is substituted during the preprocessor, not during function inlining. (edit: ninja'd)
AshleysBrain
+4  A: 

A macro can overcome this, by passing in the __LINE__ as a parameter to the invoked function.

Another, perhaps complementary approach is to pass some context to the function as a parameter, with a default value that says 'use the line number'. This is illustrated by this code snippet which is doing error handling with the pattern:

int read_byte(FILE* f,int line=0) {
  int ret = fgetc(f);
  if(-1 == ret)
     throw (line? line: __LINE__);
  return ret;
}

int read_uint16(FILE* f,int line=0) {
  int hi = read_byte(f,(line? line: __LINE__));
  int lo = read_byte(f,(line? line: __LINE__));
  return (hi<<8)|lo;
}

int main() {
  ...
  try {
    int i = read_uint16(f,__LINE__);
  } catch(int line) {
    fprintf(stderr,"Error at line %d\n",line);
  }
  ...
}

Finally, this all smacks of wanting to get a stack trace out of C/C++ code (especially in the error handling cases). Look at VALGRIND_PRINTF_BACKTRACE(format, ...)

Will
+1  A: 

You can modify your existing function slightly, and wrap it in a macro:

#include<stdlib.h>
#include<stdio.h>

#define log() real_log(__LINE__)

void real_log(int line)
{
       printf("Log [Line:%d]\n", line);
}

int main()
{
       log();
       log();
}
caf