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

C宏的创造性/有趣用途;元编程,c,macros,metaprogramming,c-preprocessor,C,Macros,Metaprogramming,C Preprocessor,我一直在寻找有趣且最好有用的C宏/定义示例,这些示例将比定义常量或最小/最大函数更广泛。我的理解是,宏应该允许某种程度的元编程(虽然我不太确定),但搜索并不能揭示太多,因此使用宏进行元编程的示例将非常受欢迎,或者解释它为什么不能工作。总的来说,我对任何“酷”的宏使用都感兴趣 另外,我知道这个问题很快就会变得“不具建设性和封闭性”,但我认为它至少可以成为一个有趣的社区维基问题 编辑:我对任何C++、任何东西都不感兴趣。搜索泛型泛型的.h。如果你想看到预处理器的滥用。< /P> 它基本上是模板之前的

我一直在寻找有趣且最好有用的C宏/定义示例,这些示例将比定义常量或最小/最大函数更广泛。我的理解是,宏应该允许某种程度的元编程(虽然我不太确定),但搜索并不能揭示太多,因此使用宏进行元编程的示例将非常受欢迎,或者解释它为什么不能工作。总的来说,我对任何“酷”的宏使用都感兴趣

另外,我知道这个问题很快就会变得“不具建设性和封闭性”,但我认为它至少可以成为一个有趣的社区维基问题


<>编辑:我对任何C++、任何东西都不感兴趣。

搜索泛型泛型的.h。如果你想看到预处理器的滥用。< /P> 它基本上是模板之前的模板样式集合。

受此启发,前几天我正在试验宏的其他“创造性”用途,下面是我迄今为止提出的一组宏,以确保它们的参数为特定的“类型”。这些宏可以用作其他宏的一部分:

#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;
}
#包括
//只能取消引用指针。
//如果x为
//数字类型(或void*)。
#定义接受PTR(x)\
((x)+sizeof(*(x))*0)
//sizeof()是在编译时计算的,并且
//如果表达式为非常量,则将失败
//在编译时。
//(void*)&数组==(void*)&数组[0]是一个
//编译时常量。
//(void*)&ptr==(void*)&ptr[0]需要
//ptr,因此不是编译时常量,
//与(void*)&int==(void*)int相同。
#定义接受ARR(x)\
((x)+sizeof(结构{int非数组:((void*)和(x)==&(x)[0]);})*0)
//(x)+sizeof(char[(void*)和(x)=(void*)和(x)[0]]]]*0)
//x可以添加到自身,也可以仅相乘
//如果是数字类型,则无法添加指针。
#定义接受数量(x)\
((x)*1)
//(((x)+(x))-(x))
//只有整数可以移位
//(%也仅适用于整数)。
//如果x不是整数,则编译失败。
#定义接受_INT(x)\

((x)这个问题最好改为“除了定义常量或最小/最大函数外,宏的正确用法是什么?”或者甚至“我什么时候应该使用宏而不是简单函数?有什么好处?”有些东西只需要宏就行了。最直接的例子是任何需要代码的行级源文件位置的东西。\ uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。