How to get a value of __LINE__ of another function (before calling that function)?

Viewed 309

For the currently existing test framework I need to pass (during the first-most call) to the function a line number of a fragment inside of that function. Something like this:

#include <stdio.h>
void func(int line_num)
{
#define LINE_NUM  (__LINE__ + 1)
  if(line_num == __LINE__) // Check the passed arg against the current line.
    printf("OK");
  else
    printf("FAIL");
}

int main(void)
{
  func(LINE_NUM); // Pass to the func the line number inside of that func.
  return 0;
}

(this is a minimalistic version of a more complex functionality).

As is the sample code prints "FAIL".

If I pass an absolute value 5, e.g. func(5) then it prints "OK". I don't like the absolute value 5 because if I add one more line in front of the func definition then the absolute value will need a correction.

Instead of #define LINE_NUM (__LINE__ + 1) I also tried the following:

1.

#define VALUE_OF(x) x
#define LINE_NUM    (VALUE_OF(__LINE__) + 1)

2.

#define VAL(a,x)    a##x
#define LOG_LINE()    ( VAL( /*Nothing*/,__LINE__) + 1)

3.

#define VALUE_OF2(x) x
#define VALUE_OF(x)     VALUE_OF2(x)
#define LINE_NUM  (VALUE_OF(__LINE__) + 1)

I'm using:

gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

In my sample code the value that func() gets is 14 (the call site line number + 1).

2 Answers

You cannot get the preprocessor to expand __LINE__ in a macro definition. That's not the way the preprocessor works.

But you can create global constants.

#include <stdio.h>

static const int func_line_num = __LINE__ + 3;
void func(int line_num)
{
  if(line_num == __LINE__) // Check the passed arg against the current line.
    printf("OK");
  else
    printf("FAIL");
}

int main(void)
{
  func(func_line_num); // Pass to the func the line number inside of that func.
  return 0;
}

If you don't like static const int, for whatever reason, you could use an enum:

enum { FUNC_LINE_NUM = __LINE__ + 3 };

Unfortunately, whether you use a global constant or an enum, you have to put the definition at file scope, which might make it somewhat distant from the use point. However, it is not immediately apparent why the precise line number of the test needs to be used, rather than (for example) the first line of the function or even any integer guaranteed to be unique:

#include <stdio.h>

// As long as all uses of __LINE__ are on different lines, the
// resulting values will be different, at least within this file.
enum { FUNC_LINE_NUM = __LINE__ };

void func(int line_num)
{
  if(line_num == FILE_LINE_NUM) // Check the passed arg against the appropriate constant.
    printf("OK");
  else
    printf("FAIL");
}

int main(void)
{
  func(func_line_num); // Pass to the func the line number inside of that func.
  return 0;
}

After @rici 's great answer and comments the closest thing to what I need is the following:

#include <stdio.h>

#define LINE_NUM_TESTER() \
    enum { LINE_NUM = __LINE__ }; \
    \
    void line_num_tester(int line_num) \
    { \
      if(line_num == __LINE__) \
        printf("OK\n"); \
      else \
        printf("FAIL. line_num: %d, __LINE__: %d.\n", line_num, __LINE__); \
    }

LINE_NUM_TESTER()

int main(void)
{
  line_num_tester(LINE_NUM);
  return 0;
}
Related