鲲鹏社区首页
中文
注册
开发者
我要评分
获取效率
正确性
完整性
易理解
在线提单
论坛求助

基础数据类型直接赋值

【说明】 对于基础数据类型(如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