You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在C90中模拟实现C99的左值数组及结构体常量成员初始化

解决方案

最优方案:利用Union兼容构造(无UB、最简洁)

C90标准明确支持Union的别名访问规则,我们可以通过一个仅内部可见的Union来安全构造不可变的struct arr对象,完全规避修改const对象的未定义行为,代码复杂度和C99原生写法几乎一致:

#include <stdio.h>

enum
{
    MUT_ARR_LEN = 4UL
};

struct mut_arr
{
    unsigned char bytes[sizeof(unsigned char const) * MUT_ARR_LEN];
};

struct arr {
    struct mut_arr const byte_arr;
};

/* 仅当前编译单元可见的构造辅助Union,对外完全隐藏实现细节 */
union arr_construction {
    struct arr immutable;
    struct mut_arr mutable;
};

static struct arr map(struct arr const* const a,
               unsigned char (*const op)(unsigned char const))
{
    union arr_construction res;
    size_t i = 0UL;

    for (; i < MUT_ARR_LEN; ++i) {
        res.mutable.bytes[i] = op(a->byte_arr.bytes[i]);
    }

    return res.immutable;
}

static unsigned char op_add_one(unsigned char const el)
{
    return el + 1;
}

static unsigned char op_print(unsigned char const el)
{
    printf("%u", el);
    return 0U;
}

int main() {
    struct arr const a1 = {{{1, 2, 3, 4}}};

    struct arr const a2 = map(&a1, &op_add_one);

    map(&a2, &op_print);

    return 0;
}

方案优势

  • 完全符合ISO C90标准,无任何未定义行为,兼容性拉满
  • 不需要额外内存复制、不需要强制类型转换,代码简洁可读
  • 纯栈分配,线程安全,完全满足约束要求
  • 辅助Union仅内部可见,对外暴露的struct arr仍然保持成员不可变的特性,符合函数式编程的不可变数据要求

简化版Memcpy方案

如果你不想引入辅助Union,也可以直接简化原来的写法,去掉多余的指针转换和不必要的const声明,规避未定义行为:

#include <string.h>

struct arr map(struct arr const* const a,
               unsigned char (*const op)(unsigned char const))
{
    /* 不要给res本身加const限定,避免修改const对象的UB */
    struct arr res = {0};
    struct mut_arr tmp = {0};
    size_t i = 0UL;

    for (; i < sizeof(tmp.bytes); ++i) {
        tmp.bytes[i] = op(a->byte_arr.bytes[i]);
    }

    /* 直接用void*传递给memcpy即可,不需要复杂的数组指针转换 */
    memcpy((void*)&res.byte_arr, &tmp, sizeof(tmp));
    return res;
}

注意

原写法中将局部变量res声明为const struct arr,之后修改其内容属于标准明确的未定义行为,遇到开启严格优化的编译器可能出现异常结果,上述两种方案均完全规避了该问题。

内容的提问来源于stack exchange,提问作者user16729031

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 17:36:04