C宏的创新/有趣用途;元编程

4
我一直在寻找有趣且应用广泛的C宏/定义示例,这些示例应该比定义常数或min/max函数更加广泛。我理解宏应该允许一定程度的元编程(虽然我不是很确定),但搜索未能揭示太多信息,因此非常欢迎提供使用宏进行元编程的示例,或者解释为什么不能使用它。总体而言,我对任何“酷”的宏用法都很感兴趣。
附注:我不感兴趣C++方面的内容。

http://www.boost.org/doc/libs/1_51_0/libs/preprocessor/doc/index.html - Mat
有些宏是必不可少的。最直接的例子是需要代码行级源文件位置的任何内容。使用宏扩展跟踪代码执行进度时,____FILE____和____LINE____是救星。 - WhozCraig
1
你可能会对P99 - C99的预处理宏和函数项目感兴趣。 - deltheil
谢谢deltheil,这看起来非常有趣。 - morphles
相关:http://stackoverflow.com/questions/13459300/c-preprocessor-pseudo-assembly-with-embedded-byte-code-interpreter-how-to-find。另请参阅:https://dev59.com/2mw15IYBdhLWcg3wZ64Y。 - luser droog
显示剩余2条评论
2个回答

6

这个问题的启发,前几天我正在尝试其他宏的“创新”用途,到目前为止,我想出了一组宏来确保它们的参数是某种“类型”。这些可以作为其他宏的一部分使用:

#include <stdio.h>

// Only pointers can be dereferenced.
// This fails to compile if x is
// numeric type (or void*).
#define ACCEPT_PTR(x) \
  ((x) + sizeof(*(x)) * 0)

// sizeof() is evaulated at compile time and
// it will fail if the expression is non-const
// at compile time.
// (void*)&array == (void*)&array[0] is a
// compile-time const.
// (void*)&ptr == (void*)&ptr[0] needs the value of
// ptr and therefore isn't a compile-time const,
// same with (void*)&int == (void*)int.
#define ACCEPT_ARR(x) \
  ((x) + sizeof(struct { int not_an_array: ((void*)&(x) == &(x)[0]); }) * 0)
//  ((x) + sizeof(char[(void*)&(x) == (void*)&(x)[0]]) * 0)

// x can be added to itself or multiplied only
// if it's a numerical type, pointers can't be added.
#define ACCEPT_NUM(x) \
  ((x) * 1)
//  (((x) + (x)) - (x))

// Only integers can be shifted
// (% also applies to integers only).
// This will fail to compile if x isn't integer.
#define ACCEPT_INT(x) \
  ((x) << 0)
//  ((x) + (x) % 2 * 0)

// x will be concatenated with "" at compile
// time only if it's a string literal. Comilation
// will fail if x isn't a string literal.
#define ACCEPT_STR(x) \
  x ""

#define ACCEPT_LVAL(x) \
  (*&(x))

int main(void)
{
  int i = 42;
  int* p = &i;
  int a[1] = { 42 };
  float f = 42.0;

  ACCEPT_NUM(i);
  ACCEPT_NUM(p[0]);
  ACCEPT_NUM(a[0]);
//  ACCEPT_NUM(p);
//  ACCEPT_NUM(a);
//  ACCEPT_NUM("42");

  ACCEPT_INT(i);
  ACCEPT_INT(p[0]);
  ACCEPT_INT(a[0]);
  ACCEPT_INT("a"[0]);
//  ACCEPT_INT(p);
//  ACCEPT_INT(a);
//  ACCEPT_INT("42");
//  ACCEPT_INT(f);

  ACCEPT_PTR(&i);
  ACCEPT_PTR(p);
  ACCEPT_PTR(a);
  ACCEPT_PTR(&a[0]);
  ACCEPT_PTR("42");
  ACCEPT_PTR(&"a"[0]);
//  ACCEPT_PTR(i);
//  ACCEPT_PTR(f);

//  ACCEPT_ARR(a); // doesn't compile with OW :(
//  ACCEPT_ARR(i);
//  ACCEPT_ARR(p);
//  ACCEPT_ARR("42"); // WTF?; compiles with gcc :(
//  ACCEPT_ARR(f);

  ACCEPT_STR("42");
//  ACCEPT_STR(i);
//  ACCEPT_STR(p);
//  ACCEPT_STR(a);
//  ACCEPT_STR(f);

  ACCEPT_LVAL(i);
  ACCEPT_LVAL(p);
  ACCEPT_LVAL(p[0]);
  ACCEPT_LVAL(a); // not exactly lval
  ACCEPT_LVAL(a[0]);
//  ACCEPT_LVAL("42"); // WTF?; compiles with gcc but not with OW :(
  ACCEPT_LVAL(f);
//  ACCEPT_LVAL(0);
//  ACCEPT_LVAL(0.0);
//  ACCEPT_LVAL('a');

  return 0;
}

1

如果你想看到预处理器的滥用,请搜索旧版本的generic.h。

这基本上是在模板出现之前的模板样式集合。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接