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

 

posted @ 2026-01-22 14:10  苏格拉底的落泪  阅读(4)  评论(0)    收藏  举报