基础数据类型直接赋值
【说明】 对于基础数据类型(如U8/U16/U32/U64等),建议直接赋值;不推荐使用内存操作函数(memset、memcpy等),避免函数栈操作的性能损耗;
【原理】 调用内存操作参数进行赋值,系统需要入栈压栈的操作,而直接赋值时不会有此类操作,能够降低编译生成的机器指令数;
【注意事项】 针对结构体等数据清零的场景,可以优先考虑结构体赋值或结构体定义阶段清零,避免针对其数据成员进行单点清零引入的可维护性风险;
【案例】
优化前:针对uint16_t类型的字段b进行初始化,按照memset_s的方式赋值,会导致额外的函数调用开销:
uint32_t Func(uint16_t a) { uint16_t b; (void)memset_s(&b, sizeof(b), 0xFF, sizeof(b)); return a + b; }
说明:以ARM体系+GCC7.3编译器为例,打开-O2优化选项,上述代码生成的汇编代码如下,memset_s的函数调用开销无法消减:
Func(unsigned short):
mov r3, #2
push {r4, lr}
sub sp, sp, #8
mov r4, r0
mov r1, r3
mov r2, #255
add r0, sp, #6
bl memset_s(void*, unsigned int, int, unsigned int)
ldrh r0, [sp, #6]
add r0, r0, r4
add sp, sp, #8
pop {r4, pc}
优化后:直接进行变量赋值:
uint32_t Func(uint16_t a)
{
uint16_t b = UINT16_MAX;
return a + b;
}
反汇编后可以看到,相关函数执行开销大大消减:
Func(unsigned short):
add r0, r0, #65280
add r0, r0, #255
bx lr
父主题: 变量