1

I'd like to create a macro whose value is the evaluation of __LINE__ at a certain point so that I can do the following:

#define LINE1 __LINE__
int a[] = {
1,
2,
3
};
#define LINE2 __LINE__
printf("There are %d rows", LINE2 - LINE1 - 2);

...but LINE2 and LINE1 end up giving me the line number of the printf statement. Any ideas?

JellicleCat
  • 28,480
  • 24
  • 109
  • 162
  • 5
    Could you do `const int blah = __LINE__;` instead? – HolyBlackCat Sep 09 '17 at 19:31
  • 5
    You can't do it that way. I'm not sure you can do it at all. The `#define LINE1` simply says 'when you see `LINE1`, replace it with `__LINE__`. But `__LINE__` evaluates to the line number where `LINE1` is used, not where it is defined. Besides, the correct way to determine the number of elements in an array is `(sizeof(a) / sizeof(a[0]))` — which works correctly even if someone places two entries on a single line, or adds a comment in the middle of the list, etc. The only time that it fails is when the 'array' is actually a pointer parameter to a function. – Jonathan Leffler Sep 09 '17 at 19:32
  • https://stackoverflow.com/a/33712984/841108 could inspire you – Basile Starynkevitch Sep 09 '17 at 19:35
  • @HolyBlackCat: That creates a variable. C does not have symbolic constants. – too honest for this site Sep 09 '17 at 19:39
  • 1
    @JonathanLeffler +1 for noticing, what OP is actually trying to do – Erki Aring Sep 09 '17 at 20:06
  • `enum { line_x = __LINE__ };` – RbMm Sep 09 '17 at 22:07

2 Answers2

4

Macro Expansion is a lazy and recursive process. It lazy because when you define a macro with #define it is not evaluated where you have defined it; rather, it will be replaced with its value where you used it. And this replacement will take place recursively until it is replaced with something that is not a macro. So,

printf("There are %d rows", LINE2 - LINE1 - 2);

will be expanded to

printf("There are %d rows", __LINE__ - __LINE__ - 2);

which in turn will be expanded to

printf("There are %d rows", N - N - 2); // N being the current line number.

You can change your code as suggested by HolyBlackCat. Instead of declaring macro using #define use const int.

const int LINE1 = __LINE__;
   .
   .
   .
const int LINE2 = __LINE__;
army007
  • 551
  • 4
  • 20
3

Silly hack:


#include <stdio.h>

int main(void)
{
struct yyy{ char buff[__LINE__ ]; } ;
#define LINE1 ((int)sizeof(struct yyy))
int a[] = {
1,
2,
3,
4
};
struct zzz{ char buff[__LINE__ ]; } ;
#define LINE2 ((int)sizeof(struct zzz))
printf("[%d,%d]There are %d rows\n", LINE1 , LINE2 , LINE2 - LINE1 - 4);

return 0;
}

And it works at file scope,too:


#include <stdio.h>

struct yyy{ char buff[__LINE__ ]; } ;
#define LINE1 ((int)sizeof(struct yyy))
int a[] = {
1,
2,
4
};
struct zzz{ char buff[__LINE__ ]; } ;
#define LINE2 ((int)sizeof(struct zzz))

int main(void)
{
printf("[%d,%d]There are %d rows\n", LINE1 , LINE2 , LINE2 - LINE1 - 4);

return 0;
}

NOTE:this does not create variables, only two (unused) structure types.


Yet another ugly trick: use enums (which are not objects, but constants_in_disguise):


#include <stdio.h>

enum { OMG=__LINE__ , } ;
int a[] = {
#define INDEX(ll) ( (ll)- ((OMG)+3))
INDEX(__LINE__),
INDEX(__LINE__),
INDEX(__LINE__),
INDEX(__LINE__),
INDEX(__LINE__),
INDEX(__LINE__)
};
enum { WTF=__LINE__ , } ;

int main(void)
{
printf("[%d,%d]There are %d rows\n", OMG , WTF , WTF - OMG - 4);

return 0;
}
wildplasser
  • 43,142
  • 8
  • 66
  • 109