【问题标题】:__typeof variables and printf__typeof 变量和 printf
【发布时间】:2014-08-22 10:34:39
【问题描述】:

如果我定义一个通用宏,使用__typeof__/typeof,有没有办法以通用方式选择printf 转换说明符?

我的意思是,例如:

#define max(a,b) \
 ({ typeof (a) _a = (a); \
    typeof (b) _b = (b); \
    DEBUG(( "%" __PRI_TYPE_PREFIX(a) > "%" __PRI_TYPE_PREFIX(b) "?", _a, _b)) \  <-- hypothetical
    _a > _b ? _a : _b; })

有可能吗?

【问题讨论】:

    标签: c gcc printf


    【解决方案1】:

    您可以使用 C11 的 _Generic 功能来执行此操作,例如

    #define printf_dec_format(x) _Generic((x), \
        char: "%c", \
        signed char: "%hhd", \
        unsigned char: "%hhu", \
        signed short: "%hd", \
        unsigned short: "%hu", \
        signed int: "%d", \
        unsigned int: "%u", \
        long int: "%ld", \
        unsigned long int: "%lu", \
        long long int: "%lld", \
        unsigned long long int: "%llu", \
        float: "%f", \
        double: "%f", \
        long double: "%Lf", \
        char *: "%s", \
        void *: "%p")
    
    #define print(x) printf(printf_dec_format(x), x)
    

    (示例取自:Rob's Programming Blog

    【讨论】:

    • 从博客链接,我可以看到只有clang支持这个! :(,截至目前我在gcc-4.6.3
    • @vyom gcc 也支持_Generic,但您需要更新的版本。
    【解决方案2】:
    #include <stdio.h>
    
    #define FMT(_pre_, x, _post_) _Generic((x), \
      char: _pre_ "%c" _post_, \
      int: _pre_ "%d" _post_, \
      long: _pre_ "%ld" _post_)
    
    int main()
    {
      int x = 42;
      long y = 432144312432321;
      printf(FMT("foo: ", x, "\n"), x);
      printf(FMT("bar: ", y, "\n"), y);
      return 0;
    }
    

    pre 和 post 的东西有点难看,但我还没有找到更好的方法。我们不能依赖 C 预处理器中的字符串连接,因为 _Generic 由编译器评估,为时已晚。

    【讨论】:

      【解决方案3】:

      以 C11 _Generic 为例(必须填写完整检查):

      #define DEBUG_INT(a, b)     DEBUG("%d %d?", (a), (b))
      #define DEBUG_DOUBLE(a, b)  DEBUG("%f %f?", (a), (b))
      #define FAIL(a, b)          assert(0)
      
      #define max(a,b) \
       ({ typeof (a) _a = (a); \
          typeof (b) _b = (b); \
          _Generic((_a), int: DEBUG_INT, double: DEBUG_DOUBLE, default: FAIL))(_a, _b); \
          _a > _b ? _a : _b; })
      

      或使用__builtin_types_compatible_p gcc 扩展:

      #define max(a,b) \
       ({ typeof (a) _a = (a); \
          typeof (b) _b = (b); \
          if (__builtin_types_compatible_p(typeof(int), _a) && __builtin_types_compatible_p(typeof(int), _a))  DEBUG_INT(_a, _b);  \
          else if  (__builtin_types_compatible_p(typeof(double), _a) && __builtin_types_compatible_p(typeof(double), _a))  DEBUG_DOUBLE(_a, _b); \
          else FAIL(_a, _b);
          _a > _b ? _a : _b; })
      

      【讨论】:

        猜你喜欢
        • 2020-08-23
        • 2015-03-17
        • 1970-01-01
        • 2015-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-12
        • 1970-01-01
        相关资源
        最近更新 更多