【问题标题】:Creative/interesting uses for C macros; metaprograming [closed]C 宏的创造性/有趣用途;元编程[关闭]
【发布时间】:2012-10-11 08:57:03
【问题描述】:

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

附:我知道这个问题很快就会变得“没有建设性和接近”,但我认为它至少可以成为有趣的社区 wiki 问题。

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

【问题讨论】:

  • 这个问题最好改写为“除了定义 const 或 min/max 函数之外,宏的正确用途是什么?”或者甚至,“我什么时候应该使用宏而不是简单的函数?有什么好处?”
  • 有些事情宏只是必需。最直接的例子是任何需要代码的行级源文件位置的东西。 ____FILE____ 和 ____LINE____ 以及它们通过宏扩展在跟踪代码执行过程中的使用是一种天赐良机
  • 您可能对P99 - Preprocessor macros and functions for C99 项目感兴趣。
  • 感谢 deltheil 这似乎很有趣。

标签: c macros metaprogramming c-preprocessor


【解决方案1】:

如果您想了解预处理器的滥用情况,请搜索旧版本的 generic.h。

它基本上是模板之前的模板样式集合。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-08
      • 2011-07-12
      相关资源
      最近更新 更多