在另一个宏中评估C宏__LINE__

时间:2017-09-09 19:27:42

标签: c macros

我想创建一个宏,其是某个点__LINE__的评估,以便我可以执行以下操作:

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

...但LINE2LINE1最终会给我printf声明的行号。有什么想法吗?

2 个答案:

答案 0 :(得分:3)

宏扩展是一个懒惰的递归过程。它是懒惰的,因为当您使用#define定义宏时,它不会在您定义它的位置进行评估;相反,它将被替换为您使用它的值。并且这种替换将以递归方式进行,直到被替换为不是宏的东西。所以,

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

将扩展为

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

反过来将扩展到

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

您可以按照HolyBlackCat的建议更改代码。而不是使用#define使用const int声明宏。

const int LINE1 = __LINE__;
   .
   .
   .
const int LINE2 = __LINE__;

答案 1 :(得分:1)

愚蠢的黑客:

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

它也适用于文件范围:

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

注意:这不会创建变量,只会创建两个(未使用的)结构类型。

又一个丑陋的伎俩:使用枚举(不是对象,而是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;
}