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

标签 c macros metaprogramming c-preprocessor

<分区>

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

附言我知道这个问题可能会很快变得“没有建设性和关闭”,但我认为它至少可以成为有趣的社区维基问题。

编辑:我对任何 C++ 都不感兴趣。

最佳答案

灵感来自 this question ,前几天我正在试验宏的其他“创造性”用途,这是我到目前为止提出的,一组宏以确保它们的参数具有特定的“类型”。这些可以用作其他宏的一部分:

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

关于C 宏的创造性/有趣用途;元编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12996356/

相关文章:

c++ - 如何将多参数模板传递给宏?

ruby - 在 Ruby 中覆盖 "for"关键字。是否可以?

c++ - 为模板类的实例分配唯一的数字标识符

编译器显示 "error lvalue required as left operand of assignment"。这是什么意思以及如何解决?

c - 字符串中不属于字符串一部分的字符的频率。

c++ - 为什么(无限)递归在 clang(和 gcc/g++)中使用 和 w/o -O3 会给出不同的结果?

c - 以毫秒精度测量时间

c++ - 替换 C/C++ 宏中的开括号字符

iphone - iOS 如何通过宏检测iPhone X、iPhone 6 plus、iPhone 6、iPhone 5、iPhone 4?

Groovy 扩展元类