Как отформатировать флаги в c? - PullRequest
0 голосов
/ 03 июля 2011

Предположим, что есть определения флагов, такие как:

SHF_WRITE     0x1
SHF_ALLOC     0x2
SHF_EXECINSTR 0x4
SHF_MASKPROC  0xf0000000

Учитывая флаг, мне нужно вывести SHF_WRITE|SHF_ALLOC, если биты 0x1 и 0x2 включены.

Как сделать трюк в C?

Ответы [ 3 ]

5 голосов
/ 03 июля 2011
#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");
}
3 голосов
/ 03 июля 2011

Просто создайте буфер символов с достаточным пространством для хранения всех возможных комбинаций строк и добавьте в него соответствующие строки для каждого подходящего набора битов.(или вы можете отказаться от буфера и написать прямо в 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
}
0 голосов
/ 03 июля 2011

ПРОБЛЕМА:

«SHF_WRITE | SHF_ALLOC» говорит «бит 0x1 ИЛИ бит 0x2», а не «биты 0x1 И 02x».

Тем не менее, если вы хотите напечатать «НЕКОТОРЫЙ MSG»если биты 0x1 и 0x2 оба были «включены» в некотором значении «флаг», вот как:

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);

И, наконец, если вы НЕ хотите печатать, если бит NO установлен, просто сделайте это: if (flag) { ... do printing ... } else { ... do nothing? ... }

...