When are anonymous structs and unions useful in C11?

戏子无情 提交于 2019-12-17 01:00:33

问题


C11 adds, among other things, 'Anonymous Structs and Unions'.

I poked around but could not find a clear explanation of when anonymous structs and unions would be useful. I ask because I don't completely understand what they are. I get that they are structs or unions without the name afterwards, but I have always (had to?) treat that as an error so I can only conceive a use for named structs.


回答1:


Anonymous union inside structures are very useful in practice. Consider that you want to implement a discriminated sum type (or tagged union), an aggregate with a boolean and either a float or a char* (i.e. a string), depending upon the boolean flag. With C11 you should be able to code

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

With C99, you'll have to name the union, and code ch->u.f and ch->u.s which is less readable and more verbose.




回答2:


A typical and real world use of anonymous structs and unions are to provide an alternative view to data. For example when implementing a 3D point type:

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;

This is useful if you interface to code that expects a 3D vector as a pointer to three doubles. Instead of doing f(&v.x) which is ugly, you can do f(v.raw) which makes your intent clear.




回答3:


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

the type struct bla has a member of a C11 anonymous structure type.

struct { int a; int b; } has no tag and the object has no name: it is an anonymous structure type.

You can access the members of the anonymous structure this way:

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:


I'm not sure why C11 allows anonymous structures inside structures. But Linux uses it with a certain language extension:

/**
 * 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;

I'm not sure if that example strictly necessary, except to make the intent clear.

EDIT: I found another similar pattern which is more clear-cut. The anonymous struct feature is used with this attribute:

#if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
#define __randomize_layout __attribute__((randomize_layout))
#define __no_randomize_layout __attribute__((no_randomize_layout))
/* This anon struct can add padding, so only enable it under randstruct. */
#define randomized_struct_fields_start  struct {
#define randomized_struct_fields_end    } __randomize_layout;
#endif

I.e. a language extension / compiler plugin to randomize field order (ASLR-style exploit "hardening"):

struct kiocb {
    struct file     *ki_filp;

    /* The 'ki_filp' pointer is shared in a union for aio */
    randomized_struct_fields_start

    loff_t          ki_pos;
    void (*ki_complete)(struct kiocb *iocb, long ret, long ret2);
    void            *private;
    int         ki_flags;
    u16         ki_hint;
    u16         ki_ioprio; /* See linux/ioprio.h */
    unsigned int        ki_cookie; /* for ->iopoll */

    randomized_struct_fields_end
};



回答5:


Well, if you declare variables from that struct only once in your code, why does it need a name?

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

And you can now write things like e.a,f.d.b,etc.

(I added the inner struct, because I think that this is one of the most usages of anonymous structs)




回答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 is doing that for a while - for example, for compiling this this and this.



来源:https://stackoverflow.com/questions/8932707/when-are-anonymous-structs-and-unions-useful-in-c11

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!