如何对数字和字符串使用 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
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