我一直在寻找有趣且最好有用的 C 宏/定义示例,这些示例比定义 const 或 min/max 函数更广泛。我的理解是宏应该允许某种程度的元编程(尽管我不确定),但是搜索并不能揭示太多,因此非常感谢使用宏进行元编程的示例,或者解释为什么它不能工作。总的来说,我对任何“酷”的宏用途都很感兴趣。
PS 我知道这个问题很快就会变得“不具建设性和关闭”,但我认为它至少可以成为有趣的社区 wiki 问题。
编辑:我对任何 C++ 都不感兴趣。
我一直在寻找有趣且最好有用的 C 宏/定义示例,这些示例比定义 const 或 min/max 函数更广泛。我的理解是宏应该允许某种程度的元编程(尽管我不确定),但是搜索并不能揭示太多,因此非常感谢使用宏进行元编程的示例,或者解释为什么它不能工作。总的来说,我对任何“酷”的宏用途都很感兴趣。
PS 我知道这个问题很快就会变得“不具建设性和关闭”,但我认为它至少可以成为有趣的社区 wiki 问题。
编辑:我对任何 C++ 都不感兴趣。
受这个问题的启发,前几天我正在尝试宏的其他“创造性”用法,这就是我到目前为止提出的,一组宏来确保它们的参数是某种“类型”。这些可以用作其他宏的一部分:
#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;
}
如果您想查看预处理器的滥用情况,请搜索旧版本的 generic.h。
它基本上是模板之前的模板样式集合。