如何对数字和字符串使用 C 宏?

How to use C macro for both numbers and strings?

    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 吗?

这是一种方法:

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

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

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

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

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

我使用 struct table 和一些功能。

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

#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