When are anonymous structs and unions useful in C11?

CStructC11

C Problem Overview


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.

C Solutions


Solution 1 - C

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.

Another way to implement some tagged union type is to use casts. The Ocaml runtime gives a lot of examples.

The SBCL implementation of Common Lisp does use some union to implement tagged union types. And GNU make also uses them.

Solution 2 - C

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.

Solution 3 - C

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

Solution 4 - C

Another useful implementation is when you are dealing with rgba colors, since you might want access each color on its own or as a single int.

typedef struct {
	union{
		struct {uint8_t a, b, g, r;};
		uint32_t val;
	};
}Color;

Now you can access the individual rgba values or the entire value, with its highest byte being r. i.e:

int main(void)
{
	Color x;
	x.r = 0x11;
	x.g = 0xAA;
	x.b = 0xCC;
	x.a = 0xFF;

	printf("%X\n", x.val);

	return 0;
}

Prints 11AACCFF

Solution 5 - C

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

Solution 6 - C

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)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongriotspeakView Question on Stackoverflow
Solution 1 - CBasile StarynkevitchView Answer on Stackoverflow
Solution 2 - CEmily L.View Answer on Stackoverflow
Solution 3 - CouahView Answer on Stackoverflow
Solution 4 - CDylan GentileView Answer on Stackoverflow
Solution 5 - CsourcejediView Answer on Stackoverflow
Solution 6 - CasaelrView Answer on Stackoverflow