【linux编程】union原理分析
union原理分析
示例
#include <stdio.h>
typedef enum {
RW_CTX_AB,
RW_CTX_C,
} rw_ctx_type_t;
typedef struct rw_context {
rw_ctx_type_t type;
union {
struct { // A + B 同时存在
A a;
B b;
};
C c; // 或者只存在 C
};
} rw_context_t;
int main () {
rw_context_t ctx;
ctx.type = RW_CTX_AB;
ctx.a; // 直接访问
ctx.b;
ctx.type = RW_CTX_C;
ctx.c; // 直接访问
}
解析:
- 匿名 union:没有名字,成员直接提升到外层 struct
- 匿名 struct:a、b 直接成为 rw_context_t 的成员
- 这是 C11 标准特性(并且 GCC/Clang 早就支持)
sizeof(rw_context_t) 等于:
max(sizeof(A) + sizeof(B), sizeof(C)) + sizeof(type)
初始化要小心:
rw_context_t ctx = {
.type = RW_CTX_AB,
.a = ...,
.b = ...,
};
或者:
rw_context_t ctx = {
.type = RW_CTX_C,
.c = ...,
};
#include <stdio.h>
#include <string.h>
/* =========================
* 模拟三种 IO 结构
* ========================= */
typedef struct {
int bio_pages;
} bio_ctx_t;
typedef struct {
int dio_fd;
} dio_ctx_t;
typedef struct {
void *user_buf;
size_t len;
} zc_ctx_t;
/* =========================
* enum:当前 rw_context 的状态
* ========================= */
typedef enum {
RW_CTX_EMPTY = 0, // 什么都没有
RW_CTX_BIO,
RW_CTX_DIO,
RW_CTX_ZEROCOPY,
} rw_ctx_kind_t;
/* =========================
* rw_context 定义
* ========================= */
typedef struct rw_context {
rw_ctx_kind_t kind;
union {
bio_ctx_t bio;
dio_ctx_t dio;
zc_ctx_t zc;
};
} rw_context_t;
/* =========================
* 初始化 / 重置
* ========================= */
void rw_ctx_init(rw_context_t *ctx)
{
memset(ctx, 0, sizeof(*ctx));
ctx->kind = RW_CTX_EMPTY;
}
void rw_ctx_reset(rw_context_t *ctx)
{
/* 如果内部有资源,这里释放 */
switch (ctx->kind) {
case RW_CTX_ZEROCOPY:
/* 示例:这里只是打印 */
printf("release zerocopy buffer\n");
break;
default:
break;
}
ctx->kind = RW_CTX_EMPTY;
}
/* =========================
* 示例:设置不同 IO 类型
* ========================= */
void rw_ctx_set_bio(rw_context_t *ctx, int pages)
{
rw_ctx_reset(ctx);
ctx->kind = RW_CTX_BIO;
ctx->bio.bio_pages = pages;
}
void rw_ctx_set_dio(rw_context_t *ctx, int fd)
{
rw_ctx_reset(ctx);
ctx->kind = RW_CTX_DIO;
ctx->dio.dio_fd = fd;
}
void rw_ctx_set_zc(rw_context_t *ctx, void *buf, size_t len)
{
rw_ctx_reset(ctx);
ctx->kind = RW_CTX_ZEROCOPY;
ctx->zc.user_buf = buf;
ctx->zc.len = len;
}
/* =========================
* 使用示例
* ========================= */
void rw_ctx_handle(const rw_context_t *ctx)
{
switch (ctx->kind) {
case RW_CTX_EMPTY:
printf("ctx is empty\n");
break;
case RW_CTX_BIO:
printf("BIO io, pages = %d\n", ctx->bio.bio_pages);
break;
case RW_CTX_DIO:
printf("DIO io, fd = %d\n", ctx->dio.dio_fd);
break;
case RW_CTX_ZEROCOPY:
printf("ZC io, buf=%p len=%zu\n",
ctx->zc.user_buf, ctx->zc.len);
break;
}
}
/* =========================
* main:完整流程演示
* ========================= */
int main(void)
{
rw_context_t ctx;
rw_ctx_init(&ctx);
rw_ctx_handle(&ctx);
rw_ctx_set_bio(&ctx, 8);
rw_ctx_handle(&ctx);
rw_ctx_set_dio(&ctx, 42);
rw_ctx_handle(&ctx);
char buffer[128];
rw_ctx_set_zc(&ctx, buffer, sizeof(buffer));
rw_ctx_handle(&ctx);
rw_ctx_reset(&ctx);
rw_ctx_handle(&ctx);
return 0;
}

浙公网安备 33010602011771号