除其他事项外,C11还增加了"匿名结构和联盟".
我四处寻找,但无法找到匿名结构和工会何时有用的明确解释.我问,因为我不完全明白它们是什么.我得知它们之后是没有名字的结构或联合,但我总是(必须?)将其视为一个错误,所以我只能设想一个用于命名结构的用法.
Bas*_*tch 52
内部结构中的匿名联合在实践中非常有用.考虑您要实现一个有区别的和类型(或标记的联合),一个带有布尔值的聚合以及一个浮点数或一个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);
}
Run Code Online (Sandbox Code Playgroud)
使用C99,您必须为联合命名,代码ch->u.f
和ch->u.s
可读性更低且更详细.
Emi*_* L. 44
匿名结构和联合的典型和现实世界的使用是提供数据的替代视图.例如,在实现3D点类型时:
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;
Run Code Online (Sandbox Code Playgroud)
如果您将代码期望3D矢量作为指向三个双精度的指针,那么这非常有用.而不是做f(&v.x)
丑陋的事情,你可以做到f(v.raw)
这一点,这使你的意图清晰.
struct bla {
struct { int a; int b; };
int c;
};
Run Code Online (Sandbox Code Playgroud)
该类型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
Run Code Online (Sandbox Code Playgroud)
小智 6
另一个有用的实现是当您处理 rgba 颜色时,因为您可能希望单独访问每种颜色或作为单个 int 访问。
typedef struct {
union{
struct {uint8_t a, b, g, r;};
uint32_t val;
};
}Color;
Run Code Online (Sandbox Code Playgroud)
现在您可以访问单个 rgba 值或整个值,其最高字节为 rie:
int main(void)
{
Color x;
x.r = 0x11;
x.g = 0xAA;
x.b = 0xCC;
x.a = 0xFF;
printf("%X\n", x.val);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
打印 11AACCFF
我不确定为什么 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;
Run Code Online (Sandbox Code Playgroud)
我不确定这个例子是否绝对必要,除了为了清楚地表明意图。
编辑:我发现了另一个更清晰的类似模式。匿名结构体功能与此属性一起使用:
#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
Run Code Online (Sandbox Code Playgroud)
即用于随机化字段顺序的语言扩展/编译器插件(ASLR 式利用“强化”):
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
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
35228 次 |
最近记录: |