类型相关的宏,用于使用令牌粘贴来打印十六进制数字?

问题描述

我想使用相同的宏来打印不同的类型:

int64_t q64 = 0x1234567890ABCDEF;
int32_t q32 = 0x12345678;
int16_t q16 = 0x1234;

PRINT_Q(64,q64);
PRINT_Q(32,q32);
PRINT_Q(16,q16);

(还有一层抽象的“层”,所以我最终得到了普通的PRINT_Q(name)宏,而不必指定64、32或16,但是在这里简化一下。)

这里是一个宏,我想简化一下:

#define PRINT_Q(MAXSIZE,name)                              \
    {                                                       \
        if(MAXSIZE==64)                                     \
            printf(" 0x%.016lX ",name);                    \
        else if(MAXSIZE==32)                                \
            printf(" 0x%.08X ",name);                      \
        else if(MAXSIZE==16)                                \
            printf(" 0x%.04X ",name);                      \
    }

是否有一种方法可以避免if-else并以某种方式用016替换0804##MAXSIZE?问题基本上是如何从0x%.016llX中的64的MAXSIZE变为016?对于MAXSIZE的其他两种情况也是如此。

解决方法

您可以使用标准C _Generic并删除size参数。它使用编译时类型检查,因此它与令牌粘贴一样高效,但类型安全且不那么混乱:

#include <inttypes.h>
#include <stdio.h>

#define PRINT_Q(n) printf(  _Generic((n),\
                              int64_t: " 0x%.016" PRIX64,\
                              int32_t: " 0x%.08"  PRIX32,\
                              int16_t: " 0x%.04"  PRIX16  \
                            ),(n) )

int main (void)
{
  int64_t q64 = 0x1234567890ABCDEF;
  int32_t q32 = 0x12345678;
  int16_t q16 = 0x1234;

  PRINT_Q(q64);
  PRINT_Q(q32);
  PRINT_Q(q16);
}

输出:

 0x1234567890ABCDEF 0x12345678 0x1234

(不过请注意,%X%PRIXnn格式说明符期望将无符号类型作为参数。请考虑将其实现为无符号类型。)