嵌入式C代码简洁性优化指南

嵌入式C代码简洁性优化指南

:clipboard: 目录

  1. 布尔表达式技巧
  2. 位运算优化
  3. 三元运算符
  4. 数组索引计算
  5. 循环优化
  6. 条件判断简化
  7. 数据结构优化
  8. 宏定义技巧
  9. 函数内联
  10. 状态机优化

技巧1: 布尔表达式简化

1.1 利用C语言隐式类型转换

:cross_mark: 冗余写法(你的原代码)

void Led_Proc()
{
    // LED0:温度超过上限
    if(Temperature_Data > TMAX)
    {
        Led_Level = 3;
        ucLed[0] = 1;
    }
    else
    {
        ucLed[0] = 0;
    }

    // LED1:温度在范围内
    if((Temperature_Data >= TMIN) && (Temperature_Data <= TMAX))
    {
        Led_Level = 6;
        ucLed[1] = 1;
    }
    else
    {
        ucLed[1] = 0;
    }

    // LED2:温度低于下限
    if(Temperature_Data < TMIN)
    {
        Led_Level = 9;
        ucLed[2] = 1;
    }
    else
    {
        ucLed[2] = 0;
    }

    // LED3:数据错误标志
    if(Data_Error == 1)
    {
        ucLed[3] = 1;
    }
    else
    {
        ucLed[3] = 0;
    }
}

行数:34行


:white_check_mark: 简洁写法(范例程序风格)

void Led_Proc()
{
    // 直接将布尔表达式结果赋值给变量
    ucLed[0] = (Temperature_Data > TMAX);
    ucLed[1] = (Temperature_Data >= TMIN) && (Temperature_Data <= TMAX);
    ucLed[2] = (Temperature_Data < TMIN);
    ucLed[3] = Data_Error;

    // PWM等级判断
    if(Temperature_Data > TMAX)
        Led_Level = 3;
    else if(Temperature_Data >= TMIN)
        Led_Level = 6;
    else
        Led_Level = 9;
}

行数:14行(减少59%)


:magnifying_glass_tilted_left: 原理解析

// C语言中:
// 真值表达式 = 1
// 假值表达式 = 0

unsigned char result;
result = (5 > 3);  // result = 1
result = (5 < 3);  // result = 0

// 因此可以直接赋值
ucLed[0] = (Temperature_Data > TMAX);
// 等价于
if(Temperature_Data > TMAX)
    ucLed[0] = 1;
else
    ucLed[0] = 0;

1.2 极致优化:利用整数除法

:white_check_mark: 范例程序的技巧

// 利用整数除法判断大小关系
ucLed[0] = (int)Temperature / Parameter_Ctrol[0];

// 原理:
// 若 Temperature >= Parameter_Ctrol[0],商≥1(真)
// 若 Temperature < Parameter_Ctrol[0],商=0(假)

:magnifying_glass_tilted_left: 真值表

Temperature=35, Parameter_Ctrol[0]=30
35 / 30 = 1(整数除法) → ucLed[0] = 1

Temperature=25, Parameter_Ctrol[0]=30
25 / 30 = 0(整数除法) → ucLed[0] = 0

复杂条件组合

// 范例程序:判断温度在范围内
ucLed[1] = (!((int)Temperature / Parameter_Ctrol[0])) &
           ((int)Temperature / Parameter_Ctrol[1]);

// 拆解:
// Part1: !((int)Temperature / Parameter_Ctrol[0])
//        → Temperature < Parameter_Ctrol[0] (上限)
// Part2: ((int)Temperature / Parameter_Ctrol[1])
//        → Temperature >= Parameter_Ctrol[1] (下限)
// 结果: (Temperature < 上限) && (Temperature >= 下限)

1.3 实战改进建议

推荐写法(平衡简洁与可读性)

void Led_Proc()
{
    // 方案1:布尔表达式(推荐)
    ucLed[0] = (Temperature_Data > TMAX);
    ucLed[1] = (Temperature_Data >= TMIN) && (Temperature_Data <= TMAX);
    ucLed[2] = (Temperature_Data < TMIN);
    ucLed[3] = Data_Error;

    // 方案2:整数除法(仅当性能关键时使用)
    // ucLed[0] = Temperature_Data / (TMAX + 1);  // 需要TMAX+1避免除0

    // PWM等级
    Led_Level = (Temperature_Data > TMAX) ? 3 :
                (Temperature_Data >= TMIN) ? 6 : 9;
}

技巧2: 位运算与逻辑运算

2.1 位运算符优化

:cross_mark: 普通写法

// 参数切换
if(Parameter_Index == 0)
    Parameter_Index = 1;
else
    Parameter_Index = 0;

:white_check_mark: 简洁写法

// 异或运算翻转
Parameter_Index ^= 1;  // 0↔1切换

// 原理:
// 0 ^ 1 = 1
// 1 ^ 1 = 0

2.2 位操作集合

// 1. 置位(设置某位为1)
ucLed[i] |= (1 << n);   // 将第n位置1

// 2. 清位(设置某位为0)
ucLed[i] &= ~(1 << n);  // 将第n位清0

// 3. 翻转
ucLed[i] ^= (1 << n);   // 将第n位翻转

// 4. 测试位
if(ucLed[i] & (1 << n)) // 测试第n位是否为1

// 5. 取反
P1 = ~temp;             // 所有位取反(LED驱动常用)

2.3 实战案例:LED驱动优化

:cross_mark: 你的原代码

void Led_Disp(unsigned char addr, enable)
{
    static unsigned char temp = 0x00;
    static unsigned char temp_old = 0xff;

    if(enable)
        temp |= 0x01 << addr;   // 置位
    else
        temp &= ~(0x01 << addr); // 清位

    if(temp != temp_old)
    {
        P1 = ~temp;
        temp_old = temp;
    }
}

分析:这个已经很简洁了!保持即可。


2.4 位域(Bit Field)技巧

:white_check_mark: 使用位域减少内存

// 原代码:使用多个字节
bit Num_Input;        // 1 bit
bit Point_Input;      // 1 bit
bit Flag_0;           // 1 bit
bit Flag_2;           // 1 bit
bit Data_Error;       // 1 bit

// 优化:使用位域结构(如果编译器不支持bit类型)
struct {
    unsigned char Num_Input   : 1;
    unsigned char Point_Input : 1;
    unsigned char Flag_0      : 1;
    unsigned char Flag_2      : 1;
    unsigned char Data_Error  : 1;
    unsigned char reserved    : 3;  // 预留3位
} Flags;

// 使用
Flags.Num_Input = 1;
if(Flags.Data_Error) { ... }

技巧3: 三元运算符

3.1 基本用法

:cross_mark: 冗长写法

if(Seg_Disp_Mode == 1)
    Seg_Disp_Mode = 2;
else
    Seg_Disp_Mode = 1;

:white_check_mark: 简洁写法

Seg_Disp_Mode = (Seg_Disp_Mode == 1) ? 2 : 1;

3.2 范例程序中的应用

// 范例:界面切换
Seg_Disp_Mode = (Seg_Disp_Mode == 1) ? 2 : 1;

// 你的代码可以改为
if(Seg_Disp_Mode != 0)
    Seg_Disp_Mode = (Seg_Disp_Mode == 1) ? 2 : 1;

3.3 嵌套三元运算符(适度使用)

:white_check_mark: PWM等级判断优化

// 原代码
if(Temperature_Data > TMAX)
    Led_Level = 3;
else if(Temperature_Data >= TMIN)
    Led_Level = 6;
else
    Led_Level = 9;

// 简洁写法
Led_Level = (Temperature_Data > TMAX) ? 3 :
            (Temperature_Data >= TMIN) ? 6 : 9;

3.4 三元运算符在数组选择中的应用

// 闪烁效果
Seg_Buf[3 + Seg_Input_Index] = Seg_Star_Flag ? Seg_Input[Seg_Input_Index] : 10;

// 等价于
if(Seg_Star_Flag)
    Seg_Buf[3 + Seg_Input_Index] = Seg_Input[Seg_Input_Index];
else
    Seg_Buf[3 + Seg_Input_Index] = 10;

技巧4: 数组索引计算技巧

4.1 范例程序的巧妙设计

:white_check_mark: 参数闪烁的索引计算

// 范例程序
bit Parameter_Index;  // 0或1

// 显示参数
Seg_Buf[2] = Parameter[0] / 10;  // 上限十位
Seg_Buf[3] = Parameter[0] % 10;  // 上限个位
Seg_Buf[4] = Parameter[1] / 10;  // 下限十位
Seg_Buf[5] = Parameter[1] % 10;  // 下限个位

// 闪烁效果:通过Parameter_Index计算偏移
Seg_Buf[2 + 2*Parameter_Index] = Seg_Star_Flag ? Parameter[Parameter_Index]/10 : 10;
Seg_Buf[3 + 2*Parameter_Index] = Seg_Star_Flag ? Parameter[Parameter_Index]%10 : 10;

:magnifying_glass_tilted_left: 索引计算解析

Parameter_Index = 0 (修改上限)
  → Seg_Buf[2 + 2*0] = Seg_Buf[2]  (上限十位)
  → Seg_Buf[3 + 2*0] = Seg_Buf[3]  (上限个位)

Parameter_Index = 1 (修改下限)
  → Seg_Buf[2 + 2*1] = Seg_Buf[4]  (下限十位)
  → Seg_Buf[3 + 2*1] = Seg_Buf[5]  (下限个位)

:cross_mark: 你的原代码(展开写法)

unsigned char Temperature_Setting_Index;  // 0或2

if(Temperature_Setting_Index == 0)  // 修改上限
{
    Seg_Buf[2] = 10;
    Seg_Buf[3] = 10;
}
if(Temperature_Setting_Index == 2)  // 修改下限
{
    Seg_Buf[4] = 10;
    Seg_Buf[5] = 10;
}

:white_check_mark: 优化建议(改用索引计算)

// 方案1:改用0/1索引
unsigned char Parameter_Index;  // 0或1

// 闪烁逻辑
if(Flag_2)
{
    Seg_Buf[2 + 2*Parameter_Index] = 10;
    Seg_Buf[3 + 2*Parameter_Index] = 10;
}

// 方案2:保持你的0/2索引,用除法
if(Flag_2)
{
    Seg_Buf[2 + Temperature_Setting_Index] = 10;
    Seg_Buf[3 + Temperature_Setting_Index] = 10;
}

4.2 数组遍历优化

:cross_mark: 展开写法

Seg_Point[3] = 0;
Seg_Point[4] = 0;
Seg_Point[5] = 0;

:white_check_mark: 循环写法

for(i = 3; i < 6; i++)
    Seg_Point[i] = 0;

// 或使用memset(需要string.h)
memset(&Seg_Point[3], 0, 3);

技巧5: 循环简化

5.1 For循环优化

:cross_mark: 你的原代码

for(j = 0; j < 3; j++)
{
    Temperature_Real[j] = 0;
}
for(i = 0; i < 3; i++)
{
    Temperature_Input_Point[i] = 0;
    Temperature_Input[i] = 13;
}

:white_check_mark: 简洁写法

// 合并循环
for(i = 0; i < 3; i++)
{
    Temperature_Real[i] = 0;
    Temperature_Input_Point[i] = 0;
    Temperature_Input[i] = 13;
}

// 或使用memset
memset(Temperature_Real, 0, 3);
memset(Temperature_Input_Point, 0, 3);
memset(Temperature_Input, 13, 3);

5.2 While循环的巧妙应用

:white_check_mark: 范例程序:四舍五入处理

// 根据小数点位置动态除法
Temperature = Seg_Input[0]*100 + Seg_Input[1]*10 + Seg_Input[2] + 5;
while(3 - Point_Wela)
{
    Temperature /= 10.0;
    Point_Wela++;
}

// 示例:Point_Wela=1(小数点在第2位)
// 循环次数:3-1=2次
// 373.0 → 37.3 → 3.73(实际只除2次)

5.3 展开小循环

// 当循环次数固定且少时,展开可能更快
// ❌ 循环写法(3次迭代)
for(i = 0; i < 3; i++)
    Seg_Buf[3 + i] = Seg_Input[i];

// ✅ 展开写法(消除循环开销)
Seg_Buf[3] = Seg_Input[0];
Seg_Buf[4] = Seg_Input[1];
Seg_Buf[5] = Seg_Input[2];

// 注意:51单片机上展开通常更快

技巧6: 条件判断简化

6.1 提前返回(Early Return)

:cross_mark: 深层嵌套

void Key_Proc()
{
    if(Key_Slow_Down == 0)
    {
        Key_Slow_Down = 1;

        Key_Val = Key_Read();
        // ... 大量代码
    }
}

:white_check_mark: 提前返回

void Key_Proc()
{
    if(Key_Slow_Down) return;  // 提前退出
    Key_Slow_Down = 1;

    Key_Val = Key_Read();
    // ... 代码不需要缩进
}

优点:减少缩进层级,提高可读性


6.2 合并条件

:cross_mark: 分散判断

if(Key_Down >= 1)
{
    if(Key_Down <= 10)
    {
        if(Seg_Input_Index <= 2)
        {
            // 处理
        }
    }
}

:white_check_mark: 合并条件

if(Key_Down >= 1 && Key_Down <= 10 && Seg_Input_Index <= 2)
{
    // 处理
}

6.3 使用查找表替代if-else

:cross_mark: 大量if-else

if(key == 1) return 0x01;
else if(key == 2) return 0x02;
else if(key == 3) return 0x04;
else if(key == 4) return 0x08;
// ...

:white_check_mark: 查找表

const unsigned char KeyMap[] = {0x01, 0x02, 0x04, 0x08, ...};
return KeyMap[key - 1];

技巧7: 数据结构优化

7.1 数组vs分散变量

:cross_mark: 你的原代码

unsigned char Temperature_Setting[4] = {3,0,2,0};
unsigned char TMAX, TMIN;

// 使用时需要转换
TMAX = Temperature_Setting[0]*10 + Temperature_Setting[1];
TMIN = Temperature_Setting[2]*10 + Temperature_Setting[3];

:white_check_mark: 范例程序(紧凑)

unsigned char Parameter[2] = {30, 20};  // 直接存储值

// 显示时才分解
Seg_Buf[2] = Parameter[0] / 10;
Seg_Buf[3] = Parameter[0] % 10;

对比

  • 你的:4字节数组 + 2字节变量 = 6字节
  • 范例:2字节数组 = 2字节(节省67%内存)

7.2 结构体封装

:white_check_mark: 使用结构体组织相关数据

// 温度相关数据封装
typedef struct {
    unsigned char input[3];         // 输入缓冲
    unsigned char input_point[3];   // 小数点标记
    unsigned char real[3];          // 实际温度
    unsigned char data;             // 当前温度值
    unsigned char index;            // 输入索引
    bit num_flag;                   // 数字输入标志
    bit point_flag;                 // 小数点标志
} Temperature_t;

Temperature_t Temp;

// 使用
Temp.input[Temp.index] = Key_Down - 1;
Temp.index++;

优点

  • 数据组织清晰
  • 便于参数传递
  • 避免全局变量污染

7.3 枚举定义常量

:cross_mark: 魔法数字

if(Key_Down == 11) { ... }  // 11是什么?
if(Key_Down == 12) { ... }  // 12是什么?

:white_check_mark: 枚举定义

enum {
    KEY_NUM_0 = 1,
    KEY_NUM_1,
    // ...
    KEY_NUM_9 = 10,
    KEY_POINT = 11,
    KEY_MODE  = 12,
    KEY_PARAM = 13,
    KEY_ADD   = 14,
    KEY_SUB   = 15,
    KEY_CONFIRM = 16
};

if(Key_Down == KEY_POINT) { ... }
if(Key_Down == KEY_MODE) { ... }

技巧8: 宏定义与常量

8.1 宏定义常量

// 硬件引脚定义
#define LED_PORT    P1
#define SEG_PORT    P0
#define SEG_LATCH   P2_6
#define SEG_WELA    P2_7

// 系统参数
#define TEMP_MAX    85
#define TEMP_MIN    0
#define PARAM_MAX   70
#define PARAM_MIN   10

// 时间常量
#define KEY_SCAN_PERIOD    10   // ms
#define SEG_REFRESH_PERIOD 50   // ms
#define BLINK_PERIOD       250  // ms
#define LONG_PRESS_TIME    500  // ms

8.2 函数宏

// 数值限制宏
#define LIMIT(val, min, max) \
    ((val) < (min) ? (min) : ((val) > (max) ? (max) : (val)))

// 使用
Temperature = LIMIT(Temperature, 0, 85);

// 数组元素个数
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

// 位操作宏
#define SET_BIT(reg, bit)   ((reg) |= (1 << (bit)))
#define CLR_BIT(reg, bit)   ((reg) &= ~(1 << (bit)))
#define TOG_BIT(reg, bit)   ((reg) ^= (1 << (bit)))
#define GET_BIT(reg, bit)   (((reg) >> (bit)) & 1)

8.3 条件编译

// 调试开关
#define DEBUG_MODE  1

#if DEBUG_MODE
    #define DEBUG_PRINT(x) printf(x)
#else
    #define DEBUG_PRINT(x)
#endif

// 使用
DEBUG_PRINT("Temperature: %d\n");  // Release版本自动删除

技巧9: 函数封装与内联

9.1 提取重复代码

:cross_mark: 重复的清除逻辑

// 你的代码中多处出现
Temperature_Input_Index = 0;
Num_Input = 0;
Point_Input = 0;
for(j = 0; j < 3; j++)
{
    Temperature_Real[j] = 0;
}
for(i = 0; i < 3; i++)
{
    Temperature_Input_Point[i] = 0;
    Temperature_Input[i] = 13;
}

:white_check_mark: 封装为函数

void Clear_Input_Data(void)
{
    unsigned char i;

    Temperature_Input_Index = 0;
    Num_Input = 0;
    Point_Input = 0;

    for(i = 0; i < 3; i++)
    {
        Temperature_Real[i] = 0;
        Temperature_Input_Point[i] = 0;
        Temperature_Input[i] = 13;
    }
}

// 使用
if(invalid_data)
{
    Clear_Input_Data();
}

9.2 内联小函数

// 将频繁调用的小函数声明为内联
#define INLINE static inline

INLINE unsigned char Is_Temp_Valid(unsigned char temp)
{
    return (temp >= TEMP_MIN && temp <= TEMP_MAX);
}

INLINE void Set_LED(unsigned char index, unsigned char state)
{
    ucLed[index] = state;
}

// 使用
if(Is_Temp_Valid(Temperature_Data))
{
    Set_LED(0, 1);
}

技巧10: 状态机优化

10.1 使用switch-case优化if-else

:cross_mark: 你的原代码(部分)

if(Key_Down == 11) { ... }
if(Key_Down == 16) { ... }
if(Key_Down == 12) { ... }
if(Key_Down == 13) { ... }
if(Key_Down == 14) { ... }
if(Key_Down == 15) { ... }

:white_check_mark: 使用switch-case

switch(Key_Down)
{
    case KEY_POINT:    // 11
        // 处理小数点
        break;

    case KEY_MODE:     // 12
        // 模式切换
        break;

    case KEY_PARAM:    // 13
        // 参数切换
        break;

    case KEY_ADD:      // 14
        // 参数加1
        break;

    case KEY_SUB:      // 15
        // 参数减1
        break;

    case KEY_CONFIRM:  // 16
        // 确认输入
        break;

    default:
        if(Key_Down >= 1 && Key_Down <= 10)
        {
            // 数字输入
        }
        break;
}

10.2 函数指针表(高级)

// 定义函数指针类型
typedef void (*KeyHandler)(void);

// 按键处理函数
void Handle_Point(void) { /* ... */ }
void Handle_Mode(void)  { /* ... */ }
void Handle_Param(void) { /* ... */ }
void Handle_Add(void)   { /* ... */ }
void Handle_Sub(void)   { /* ... */ }
void Handle_Confirm(void) { /* ... */ }

// 函数指针表
const KeyHandler KeyHandlers[] =
{
    NULL,           // 0
    NULL,           // 1-10 (数字输入)
    // ...
    NULL,           // 10
    Handle_Point,   // 11
    Handle_Mode,    // 12
    Handle_Param,   // 13
    Handle_Add,     // 14
    Handle_Sub,     // 15
    Handle_Confirm  // 16
};

// 使用
if(Key_Down >= 1 && Key_Down <= 16 && KeyHandlers[Key_Down])
{
    KeyHandlers[Key_Down]();
}

:bullseye: 实战重构:优化你的main.c

重构目标

将你的451行代码优化到约300行,同时保持可读性。


重构1: Led_Proc函数

原代码(34行)

void Led_Proc()
{
    if(Temperature_Data > TMAX)
    {
        Led_Level = 3;
        ucLed[0] = 1;
    }
    else
    {
        ucLed[0] = 0;
    }

    if((Temperature_Data >= TMIN) && (Temperature_Data <= TMAX))
    {
        Led_Level = 6;
        ucLed[1] = 1;
    }
    else
    {
        ucLed[1] = 0;
    }

    if(Temperature_Data < TMIN)
    {
        Led_Level = 9;
        ucLed[2] = 1;
    }
    else
    {
        ucLed[2] = 0;
    }

    if(Data_Error == 1)
    {
        ucLed[3] = 1;
    }
    else
    {
        ucLed[3] = 0;
    }
}

优化后(8行,减少76%)

void Led_Proc()
{
    // 直接赋值布尔表达式
    ucLed[0] = (Temperature_Data > TMAX);
    ucLed[1] = (Temperature_Data >= TMIN) && (Temperature_Data <= TMAX);
    ucLed[2] = (Temperature_Data < TMIN);
    ucLed[3] = Data_Error;

    // PWM等级(三元运算符)
    Led_Level = (Temperature_Data > TMAX) ? 3 :
                (Temperature_Data >= TMIN) ? 6 : 9;
}

重构2: 输入数据清除

原代码(重复3次,每次14行)

Temperature_Input_Index = 0;
Num_Input = 0;
Point_Input = 0;
for(j = 0; j < 3; j++)
{
    Temperature_Real[j] = 0;
}
for(i = 0; i < 3; i++)
{
    Temperature_Input_Point[i] = 0;
    Temperature_Input[i] = 13;
}

优化后(封装为函数)

void Clear_Input(void)
{
    unsigned char i;

    Temperature_Input_Index = 0;
    Num_Input = 0;
    Point_Input = 0;

    memset(Temperature_Real, 0, 3);
    memset(Temperature_Input_Point, 0, 3);
    memset(Temperature_Input, 13, 3);
}

// 使用(替换3次重复代码)
Clear_Input();

节省:42行 → 13行(减少69%)


重构3: 参数调整逻辑

原代码(按键14,35行)

if(Key_Down == 14)
{
    if(Seg_Dis_Mode == 2)
    {
        Temperature_Setting[Temperature_Setting_Index + 1]++;
        if(Temperature_Setting[Temperature_Setting_Index + 1] == 10)
        {
            Temperature_Setting[Temperature_Setting_Index + 1] = 0;
            Temperature_Setting[Temperature_Setting_Index]++;
        }
        if((Temperature_Setting[Temperature_Setting_Index] == 7) &&
           (Temperature_Setting[Temperature_Setting_Index + 1] == 1))
        {
            Temperature_Setting[Temperature_Setting_Index] = 7;
            Temperature_Setting[Temperature_Setting_Index + 1] = 0;
        }
    }
}

if(Key_Old == 14)
{
    if(Seg_Dis_Mode == 2)
    {
        if(Key_Long0 >= 500)
        {
            // 重复上面的逻辑...
        }
    }
}

优化后(提取公共函数)

void Adjust_Parameter(unsigned char delta)
{
    unsigned char* param = &Temperature_Setting[Temperature_Setting_Index];
    unsigned char val = param[0] * 10 + param[1];

    val += delta;
    val = LIMIT(val, PARAM_MIN, PARAM_MAX);  // 限制10-70

    param[0] = val / 10;
    param[1] = val % 10;
}

// 按键处理
if(Key_Down == 14 || (Key_Old == 14 && Key_Long0 >= 500))
{
    if(Seg_Dis_Mode == 2)
        Adjust_Parameter(1);  // +1
}

if(Key_Down == 15 || (Key_Old == 15 && Key_Long1 >= 500))
{
    if(Seg_Dis_Mode == 2)
        Adjust_Parameter(-1);  // -1
}

节省:70行 → 25行(减少64%)


重构4: 闪烁逻辑优化

原代码

if(Flag_2)
{
    if(Temperature_Setting_Index == 0)
    {
        Seg_Buf[2] = 10;
        Seg_Buf[3] = 10;
    }
    if(Temperature_Setting_Index == 2)
    {
        Seg_Buf[4] = 10;
        Seg_Buf[5] = 10;
    }
}

优化后(数组索引计算)

// 改用0/1索引
unsigned char Parameter_Index;  // 0或1,不再是0/2

// 按键13切换
Parameter_Index ^= 1;  // 0↔1切换

// 闪烁逻辑
if(Flag_2)
{
    Seg_Buf[2 + 2*Parameter_Index] = 10;
    Seg_Buf[3 + 2*Parameter_Index] = 10;
}

节省:12行 → 4行(减少67%)


:bar_chart: 优化效果总结

函数/模块 原代码行数 优化后行数 减少比例
Led_Proc 34行 8行 76% ↓
Clear_Input 42行(重复3次) 13行 69% ↓
参数调整 70行 25行 64% ↓
闪烁逻辑 12行 4行 67% ↓
总计 158行 50行 68% ↓

预计总优化:451行 → 约300行(减少33%)


:warning: 注意事项

1. 可读性优先原则

// ❌ 过度优化,难以理解
x = (a & b) | (~a & c);

// ✅ 清晰表达
if(a)
    x = b;
else
    x = c;

2. 避免过度使用宏

// ❌ 危险的宏
#define SQUARE(x) x * x
SQUARE(a + b);  // 展开为 a + b * a + b(错误!)

// ✅ 安全的宏
#define SQUARE(x) ((x) * (x))
SQUARE(a + b);  // 展开为 ((a + b) * (a + b))

// ✅ 更好:使用内联函数
INLINE unsigned int Square(unsigned int x)
{
    return x * x;
}

3. 性能vs可读性权衡

// 高可读性(推荐)
ucLed[0] = (Temperature_Data > TMAX);

// 高性能但晦涩(仅在关键路径使用)
ucLed[0] = Temperature_Data / (TMAX + 1);

4. 团队协作考虑

  • 简洁代码需要团队统一风格
  • 注释说明复杂技巧
  • 代码审查时验证可读性

:graduation_cap: 学习路径

初级(立即可用)

  1. :white_check_mark: 布尔表达式赋值
  2. :white_check_mark: 三元运算符
  3. :white_check_mark: 提前返回
  4. :white_check_mark: 宏定义常量

中级(理解后使用)

  1. :white_check_mark: 位运算优化
  2. :white_check_mark: 数组索引计算
  3. :white_check_mark: 函数封装
  4. :white_check_mark: 查找表

高级(谨慎使用)

  1. :warning: 复杂位运算表达式
  2. :warning: 函数指针表
  3. :warning: 嵌套三元运算符
  4. :warning: 宏函数

:books: 推荐实践

第1步:优化你的Led_Proc

// 立即改进,减少76%代码
void Led_Proc()
{
    ucLed[0] = (Temperature_Data > TMAX);
    ucLed[1] = (Temperature_Data >= TMIN) && (Temperature_Data <= TMAX);
    ucLed[2] = (Temperature_Data < TMIN);
    ucLed[3] = Data_Error;

    Led_Level = (Temperature_Data > TMAX) ? 3 :
                (Temperature_Data >= TMIN) ? 6 : 9;
}

第2步:封装Clear_Input函数

void Clear_Input(void)
{
    unsigned char i;
    Temperature_Input_Index = 0;
    Num_Input = 0;
    Point_Input = 0;

    for(i = 0; i < 3; i++)
    {
        Temperature_Real[i] = 0;
        Temperature_Input_Point[i] = 0;
        Temperature_Input[i] = 13;
    }
}

第3步:添加宏定义

#define TEMP_MAX    85
#define TEMP_MIN    0
#define PARAM_MAX   70
#define PARAM_MIN   10

#define KEY_POINT   11
#define KEY_MODE    12
#define KEY_PARAM   13
#define KEY_ADD     14
#define KEY_SUB     15
#define KEY_CONFIRM 16

:bullseye: 总结

代码简洁性的黄金法则

  1. 消除重复:提取公共代码为函数
  2. 直接表达:布尔值直接赋值,不用if-else
  3. 利用运算符:三元运算符、位运算
  4. 优化结构:数组索引计算替代条件判断
  5. 宏定义常量:消除魔法数字
  6. 提前返回:减少嵌套层级
  7. 平衡权衡:简洁但不失可读性

实战检查清单

  • 是否有重复代码可以提取为函数?
  • if-else赋值0/1能否改为布尔表达式?
  • 是否使用了魔法数字?
  • 条件判断能否用三元运算符?
  • 多个if能否改为switch-case?
  • 循环是否可以合并?
  • 数组操作能否用memset?
  • 变量命名是否语义化?

文档创建时间:2026-01-31
适用场景:51单片机嵌入式C编程
难度等级:初级 → 高级
预期效果:代码减少30-50%,可读性保持或提升