【问题标题】:How to use C macro for both numbers and strings?如何将 C 宏用于数字和字符串?
【发布时间】:2021-03-24 16:01:14
【问题描述】:
    if (termAttributes.c_lflag & OPOST)
      puts("c_lflag = OPOST");
    if (termAttributes.c_lflag & OLCUC)
      puts("c_lflag = OLCUC");

我有一些类似上面的代码。我想把它简化成这样。

TCFLAGPRINT(termAttributes, c_lflag, OPOST)
TCFLAGPRINT(termAttributes, c_lflag, OLCUC)

谁能说明如何定义 TCFLAGPRINT?

【问题讨论】:

  • 具体是什么问题?把宏名改成字符串形式吧?

标签: c macros c-preprocessor


【解决方案1】:

这是一种方法:

#define TCFLAGPRINT(tio, field, flag) \
    do { \
        if ((tio).field & (flag))   \
            puts(#field " = " #flag); \
    } while (0)

do { } while (0) 包装器是一个常见的习惯用法,它强制您在宏调用的末尾添加分号。 (在这种情况下,它还会阻止您在宏调用后添加else。)

类函数宏的替换文本中宏参数名称前的#运算符将参数名称转换为字符串文字。

#field " = " #flag 将三个字符串文字连接成一个字符串常量。

【讨论】:

    【解决方案2】:

    我经常打印位掩码,所以我想出了自己的机制。

    我使用struct 表和一些函数。

    我从库中提取了一些代码来说明:

    #include <stdio.h>
    #include <string.h>
    #include <termios.h>
    
    typedef struct {
        unsigned long tgb_val;
        const char *tgb_tag;
        const char *tgb_reason;
    } tgb_t;
    
    #define TGBEOT \
        { .tgb_tag = NULL }
    
    #define TGBMORE(_tgb) \
        _tgb->tgb_tag != NULL
    
    #define _TGBFORALL(_tgb) \
        ;  TGBMORE(_tgb);  ++_tgb
    #define TGBFORALL(_tga,_tgb) \
        _tgb = _tga;  TGBMORE(_tgb);  ++_tgb
    
    #define TGBDUAL(_sym) \
        { .tgb_val = _sym, .tgb_tag = #_sym },
    
    tgb_t lflag_tgb[] = {
        TGBDUAL(OPOST)
        TGBDUAL(OLCUC)
        TGBEOT
    };
    
    // tgbmskdcd -- decode mask value
    char *
    tgbmskdcd(char *buf,const tgb_t *tgb,unsigned long val)
    {
        const char *tag;
        int sep;
        char *bp;
        int len;
    
        bp = buf;
        *bp = 0;
        sep = 0;
    
        for (TGBFORALL(tgb,tgb)) {
            if ((val & tgb->tgb_val) == 0)
                continue;
    
            if (sep)
                *bp++ = ' ';
            sep = 1;
    
            tag = tgb->tgb_tag;
            len = strlen(tag);
            strcpy(bp,tag);
            bp += len;
        }
    
        return buf;
    }
    
    int
    main(void)
    {
        struct termios term;
        char buf[100];
    
        tcgetattr(1,&term);
        printf("c_lflag: %s\n",tgbmskdcd(buf,lflag_tgb,term.c_lflag));
    
        return 0;
    }
    

    这是输出:

    c_lflag: OPOST OLCUC
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-22
      • 1970-01-01
      • 2021-10-04
      • 1970-01-01
      • 2013-09-05
      • 2017-03-28
      • 1970-01-01
      相关资源
      最近更新 更多