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

如何简化计算LHS/RHS操作数表达式的嵌套switch语句?

简化动态类型比较函数的嵌套Switch实现

问题描述

我正在编写一个函数,用于计算由LHS(左操作数)、RHS(右操作数)和测试操作符构成的数学表达式结果,例如X == Y、Z > W、U < Q这类表达式,其中X、Y等可为任意标准C类型的值。

下方是该函数的初步实现,但嵌套switch语句重复度极高:

  1. 每种LHS类型对应结构相似的代码块,需根据RHS类型和测试操作符计算结果;
  2. 每种RHS类型又对应结构相似的代码块,需根据测试操作符计算结果。

这种结构不仅冗长,还极易出错。考虑到所有标准C类型(如char、int、long、float、double等)至少有14种,每个LHS类型对应至少14个RHS分支,每个分支内还有测试操作符分支,代码量极大。

我尝试用宏实现简化,但遇到无法解决的类型提升问题——需对LHS或RHS类型适当提升以避免编译器警告。请问该如何简化这类嵌套switch语句?

原实现代码:

#include <stdint.h>
#include <stdbool.h>

struct operand {
    enum op_type {
        u8,i8,u16,i16,u32,i32,u64,i64,f,d
    } type;

    union op_value{
        uint8_t u8;
        int8_t i8;
        uint16_t u16;
        int16_t i16;
        /*etc...*/
    } value;
};

enum operator {
    equal, greater, lesser
};

bool test_operands(struct operand lhs, struct operand rhs, enum operator test)
{
    bool test_result;

    switch (lhs.type) {
    /* lhs */
    case u8:
        /* rhs */
        switch (rhs.type) {
        case u8:
            /* test */
            switch (test) {
            case equal:
                test_result = lhs.value.u8 == rhs.value.u8;
                break;
            case greater:
                test_result = lhs.value.u8 > rhs.value.u8;
                break;
            case lesser:
                test_result = lhs.value.u8 < rhs.value.u8;
                break;
            }
            break;
        case i8:
            /* test
             * same as above but with rhs.value.i8 used instead */
            break;
        case u16:
            /* test
             * need to promote lhs.value.u8 to u16 to avoid compiler warnings */
            switch (test) {
            case equal:
                test_result = (uint16_t)lhs.value.u8 == rhs.value.u16;
                break;
            case greater:
                test_result = (uint16_t)lhs.value.u8 > rhs.value.u16;
                break;
            case lesser:
                test_result = (uint16_t)lhs.value.u8 < rhs.value.u16;
                break;
            }
            break;
        case i16:
            break;
        /* etc...*/
        }
        break;

    /* lhs */
    case i8:
        /* same as above but with lhs.value.i8 used instead */
        break;

    /* etc... */
    }

    return test_result;
}

解决方案

方法1:统一类型提升到最大兼容类型

核心思路是将所有操作数转换到一个足够大的公共类型(整数用int64_t/uint64_t,浮点数用double),再在统一类型上执行比较,避免逐个类型分支处理。

#include <stdint.h>
#include <stdbool.h>
#include <math.h>

struct operand {
    enum op_type {
        u8,i8,u16,i16,u32,i32,u64,i64,f,d
    } type;

    union op_value{
        uint8_t u8;
        int8_t i8;
        uint16_t u16;
        int16_t i16;
        uint32_t u32;
        int32_t i32;
        uint64_t u64;
        int64_t i64;
        float f;
        double d;
    } value;
};

enum operator {
    equal, greater, lesser
};

// 辅助函数:将操作数转换为统一类型
double operand_to_double(struct operand op) {
    switch(op.type) {
        case u8: return (double)op.value.u8;
        case i8: return (double)op.value.i8;
        case u16: return (double)op.value.u16;
        case i16: return (double)op.value.i16;
        case u32: return (double)op.value.u32;
        case i32: return (double)op.value.i32;
        case u64: return (double)op.value.u64;
        case i64: return (double)op.value.i64;
        case f: return (double)op.value.f;
        case d: return op.value.d;
        default: return 0.0;
    }
}

bool test_operands(struct operand lhs, struct operand rhs, enum operator test)
{
    double lhs_val = operand_to_double(lhs);
    double rhs_val = operand_to_double(rhs);

    switch(test) {
        case equal: return fabs(lhs_val - rhs_val) < 1e-9; // 浮点数相等需容错
        case greater: return lhs_val > rhs_val;
        case lesser: return lhs_val < rhs_val;
        default: return false;
    }
}

注意:若需要严格精确的整数比较,可拆分逻辑:先判断是否均为整数类型,用int64_t/uint64_t比较,否则用double。

方法2:使用函数跳转表

构建二维函数表(LHS类型 × RHS类型),每个表项对应类型组合的比较函数,将类型提升逻辑封装到函数中,避免嵌套switch。

#include <stdint.h>
#include <stdbool.h>

struct operand {
    enum op_type {
        u8,i8,u16,i16,u32,i32,u64,i64,f,d, OP_TYPE_COUNT
    } type;

    union op_value{
        uint8_t u8;
        int8_t i8;
        uint16_t u16;
        int16_t i16;
        uint32_t u32;
        int32_t i32;
        uint64_t u64;
        int64_t i64;
        float f;
        double d;
    } value;
};

enum operator {
    equal, greater, lesser
};

// 定义比较函数类型
typedef bool (*CompareFunc)(struct operand lhs, struct operand rhs, enum operator test);

// 具体类型组合的比较函数
bool compare_u8_u8(struct operand lhs, struct operand rhs, enum operator test) {
    uint8_t a = lhs.value.u8;
    uint8_t b = rhs.value.u8;
    switch(test) {
        case equal: return a == b;
        case greater: return a > b;
        case lesser: return a < b;
        default: return false;
    }
}

bool compare_u8_u16(struct operand lhs, struct operand rhs, enum operator test) {
    uint16_t a = (uint16_t)lhs.value.u8;
    uint16_t b = rhs.value.u16;
    switch(test) {
        case equal: return a == b;
        case greater: return a > b;
        case lesser: return a < b;
        default: return false;
    }
}

// 填充其他类型组合的比较函数...

// 构建函数表
CompareFunc compare_table[OP_TYPE_COUNT][OP_TYPE_COUNT] = {
    [u8][u8] = compare_u8_u8,
    [u8][u16] = compare_u8_u16,
    // 填充其他表项...
};

bool test_operands(struct operand lhs, struct operand rhs, enum operator test)
{
    if(lhs.type >= OP_TYPE_COUNT || rhs.type >= OP_TYPE_COUNT) {
        return false;
    }
    CompareFunc func = compare_table[lhs.type][rhs.type];
    return func ? func(lhs, rhs, test) : false;
}

方法3:宏生成重复代码

用宏遍历所有类型组合,自动生成分支代码和类型提升逻辑,避免手动编写重复代码。

#include <stdint.h>
#include <stdbool.h>

struct operand {
    enum op_type {
        u8,i8,u16,i16,u32,i32,u64,i64,f,d
    } type;

    union op_value{
        uint8_t u8;
        int8_t i8;
        uint16_t u16;
        int16_t i16;
        uint32_t u32;
        int32_t i32;
        uint64_t u64;
        int64_t i64;
        float f;
        double d;
    } value;
};

enum operator {
    equal, greater, lesser
};

// 定义类型对应的C类型和提升目标类型
#define TYPE_LIST \
    TYPE(u8, uint8_t, uint64_t) \
    TYPE(i8, int8_t, int64_t) \
    TYPE(u16, uint16_t, uint64_t) \
    TYPE(i16, int16_t, int64_t) \
    TYPE(u32, uint32_t, uint64_t) \
    TYPE(i32, int32_t, int64_t) \
    TYPE(u64, uint64_t, uint64_t) \
    TYPE(i64, int64_t, int64_t) \
    TYPE(f, float, double) \
    TYPE(d, double, double)

// 宏:生成单个RHS类型的处理分支
#define GEN_RHS_CASE(LHS_ENUM, LHS_TYPE, LHS_PROMOTE) \
    case LHS_ENUM: \
        switch(rhs.type) { \
            TYPE_LIST \
            TYPE(RHS_ENUM, RHS_TYPE, RHS_PROMOTE) \
            { \
                case RHS_ENUM: { \
                    LHS_PROMOTE lhs_val = (LHS_PROMOTE)lhs.value.LHS_ENUM; \
                    RHS_PROMOTE rhs_val = (RHS_PROMOTE)rhs.value.RHS_ENUM; \
                    switch(test) { \
                        case equal: test_result = lhs_val == rhs_val; break; \
                        case greater: test_result = lhs_val > rhs_val; break; \
                        case lesser: test_result = lhs_val < rhs_val; break; \
                    } \
                    break; \
                } \
            } \
            default: test_result = false; break; \
        } \
        break;

bool test_operands(struct operand lhs, struct operand rhs, enum operator test)
{
    bool test_result = false;

    switch(lhs.type) {
        TYPE_LIST
        TYPE(LHS_ENUM, LHS_TYPE, LHS_PROMOTE)
        {
            GEN_RHS_CASE(LHS_ENUM, LHS_TYPE, LHS_PROMOTE)
        }
        default: test_result = false; break;
    }

    return test_result;
}

// 清理宏定义
#undef TYPE
#undef GEN_RHS_CASE
#undef TYPE_LIST

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 23:54:28