Подтвердить что ты не робот

Какие анонимные структуры и союзы полезны для C11?

C11 добавляет, помимо прочего, "Анонимные структуры и союзы".

Я ткнул, но не смог найти ясного объяснения, когда полезны анонимные структуры и союзы. Я спрашиваю, потому что я не совсем понимаю, что это такое. Я получаю, что они являются структурами или объединениями без имени впоследствии, но я всегда (должен был?) Рассматривать это как ошибку, поэтому я могу только представить себе использование для названных структур.

4b9b3361

Ответ 1

Анонимные внутриутробные структуры очень полезны на практике. Подумайте, что вы хотите реализовать дискриминированный тип суммы (или tagged union), совокупность с логическим значением и либо float, либо char* ( т.е. строка), в зависимости от булевского флага. С C11 вы должны иметь возможность кодировать

typedef struct {
    bool is_float;
    union {
       float f;
       char* s;
    };
} mychoice_t;

double as_float(mychoice_t* ch) 
{ 
   if (ch->is_float) return ch->f;
   else return atof(ch->s);
}

С C99 вам нужно будет назвать объединение и код ch->u.f и ch->u.s, который будет менее читабельным и более подробным.

Ответ 2

Типичным и реальным использованием анонимных структур и объединений является предоставление альтернативного представления данных. Например, при реализации трехмерного точечного типа:

typedef struct {
    union{
        struct{
            double x; 
            double y;
            double z;
        };
        double raw[3];
    };
}vec3d_t;

vec3d_t v;
v.x = 4.0;
v.raw[1] = 3.0; // Equivalent to v.y = 3.0
v.z = 2.0;

Это полезно, если вы взаимодействуете с кодом, который ожидает 3D-вектор как указатель на три удвоения. Вместо f(&v.x), который является уродливым, вы можете сделать f(v.raw), что делает ваше намерение понятным.

Ответ 3

struct bla {
    struct { int a; int b; };
    int c;
};

тип struct bla имеет член типа анонимной структуры C11.

struct { int a; int b; } не имеет тега, и объект не имеет имени: это анонимный тип структуры.

Вы можете получить доступ к элементам анонимной структуры следующим образом:

struct bla myobject;
myobject.a = 1;  // a is a member of the anonymous structure inside struct bla   
myobject.b = 2;  // same for b
myobject.c = 3;  // c is a member of the structure struct bla

Ответ 4

Я не уверен, почему C11 допускает анонимные структуры внутри структур. Но Linux использует его с определенным расширением языка. Главным образом, я думаю, что это должно прояснить намерение:

/**
 * struct blk_mq_ctx - State for a software queue facing the submitting CPUs
 */
struct blk_mq_ctx {
    struct {
        spinlock_t      lock;
        struct list_head    rq_lists[HCTX_MAX_TYPES];
    } ____cacheline_aligned_in_smp;

    /* ... other fields without explicit alignment annotations ... */

} ____cacheline_aligned_in_smp;

Это может быть полезно на практике, если кто-то собирает Linux с плагином компилятора для рандомизации порядка полей (эксплойт в стиле ASLR).

Ответ 5

Ну, если вы объявляете переменные из этой структуры только один раз в своем коде, зачем ему нужно имя?

struct {
 int a;
 struct {
  int b;
  int c;
 } d;
} e,f;

Теперь вы можете писать такие вещи, как e.a, f.d.b и т.д.

(Я добавил внутреннюю структуру, потому что я считаю, что это одно из самых привычных анонимных структур)

Ответ 6

struct Lock;
int lock(Lock*);
...

struct Queue
{
    Lock;
    char buf[QBUFSIZE];
    char *rp;
    char *wp;
}

qputc(Queue* q, char c){
    lock(q);
    ...
}

update3: ken c делает это некоторое время - например, для компиляции this и this.