假设有标志定义,例如:
SHF_WRITE 0x1
SHF_ALLOC 0x2
SHF_EXECINSTR 0x4
SHF_MASKPROC 0xf0000000
给定一个标志,如果SHF_WRITE|SHF_ALLOC
和0x1
位开启,我需要输出0x2
。
如何用C做技巧?
答案 0 :(得分:5)
#define V(n) { n, #n }
struct Code {
int value;
char *name;
} decode[] = {
V(SHF_WRITE),
V(SHF_ALLOC),
{ 0, NULL },
};
void f(const int x) {
struct Code *c = decode;
int beenthere = 0;
for(; c->name; ++c)
if(x & c->value)
printf("%s%s", beenthere++ ? "|" : "", c->name);
if(beenthere)
printf("\n");
}
答案 1 :(得分:3)
只需创建一个具有足够空间的字符缓冲区来保存所有可能的字符串组合,并为每个适用的位集添加适当的字符串。 (或者你可以放弃缓冲区并直接写入stdout,你的选择)这是一个天真的实现你如何做这样的事情:
void print_flags(int flag)
{
#define BUFLEN (9+9+13+12+3+1)
/* for the text, pipes and null terminator*/
#define PAIRLEN 4
static struct { int value; const char *string; } pair[] =
{
{ SHF_WRITE, "SHF_WRITE" },
{ SHF_ALLOC, "SHF_ALLOC" },
{ SHF_EXECINSTR, "SHF_EXECINSTR" },
{ SHF_MASKPROC, "SHF_MASKPROC" },
};
char buf[BUFLEN]; /* declare the buffer */
char *write = buf; /* and a "write" pointer */
int i;
for (i = 0; i < PAIRLEN; i++)
{
if ((flag & pair[i].value) == pair[i].value) /* if flag is set... */
{
size_t written = write - buf;
write += _snprintf(write, BUFLEN-written, "%s%s",
written > 0 ? "|" : "",
pair[i].string); /* write to the buffer */
}
}
if (write != buf) /* if any of the flags were set... */
{
*write = '\0'; /* null terminate (just in case) */
printf("(%s)", buf); /* print out the buffer */
}
#undef PAIRLEN
#undef BUFLEN
}
答案 2 :(得分:0)
问题:
“SHF_WRITE | SHF_ALLOC”表示“位0x1或位0x2”,而不是“位0x1 AND 02x”。
尽管如此,如果您想要打印“SOME MSG”,如果位0x1和0x2在某个值“flag”中都“打开”,那么方法如下:
if (flag & SHF_WRITE & SHF_ALLOC)
printf ("SOME MSG, flag= 0x%x\n", flag);
如果要打印值中“on”的任何位的文本表示,您可能会执行以下操作:
char buf[80] = '\0';
if (flag & SHF_WRITE)
strcpy (buf, " SHF_WRITE");
if (flag & SHF_ALLOC)
strcpy (buf, " SHF_ALLOC");
...
printf ("SOME MSG, flag= %s\n", buf);
最后,如果您不想打印,如果没有设置位,请执行以下操作:
if (flag)
{
... do printing ...
}
else
{
... do nothing? ...
}