开发者社区> 问答> 正文

c语言关键字restrict例子的问题

void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val)
{
    *ptrA += *val;
    *ptrB += *val;
}

我写了个main函数来调用它:

int main(void)
{
    size_t i = 10; 
    size_t j = 0;

    updatePtrs(&i, &j, &i);

    printf("i = %lu\n", i); 
    printf("j = %lu\n", j); 

    return 0;
}

按照维基百科中的解释,用了restrict关键字,val对应的值只会被load一次,j的值应该输出为10,而实际情况是输出20。

是否我对restrict的理解有误,或者需要在编译时加入特定选项?谢谢回答。

展开
收起
杨冬芳 2016-05-30 16:44:30 1973 0
1 条回答
写回答
取消 提交回答
  • IT从业

    你对于restrict的理解是对的,只是楼主忽略了一件事情,这个关键字本身是用来帮助编译器优化代码的
    怎么样优化呢,是告诉编译器,对于这个指针指向的值来讲,我只用这个指针修改,不会通过其他的指针修改,但是你的代码存在undefined behavior如果没有生成楼主期望的代码,可以试着开启小幅度的编译器优化(比如对于gcc 开一个-O1汇编代码就会产生明显的变化)

    下面的代码是在gcc 4.8.3开启-O1的情况下生成的,代码区别就是 有没有 restrict关键字

    // void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val)
    updatePtrs:
    .LFB3:
        .cfi_startproc
        movl    4(%esp), %ecx
        movl    8(%esp), %eax
        movl    12(%esp), %edx    //将各地址存在寄存器
        movl    (%edx), %edx    //将*val存到 %edx备用,这是唯一的一次加载,以下用的都是*val的这个副本
        addl    %edx, (%ecx)
        addl    %edx, (%eax)
        ret
        .cfi_endproc
    .LFE3:
        .size    updatePtrs, .-updatePtrs
        .globl    updatePtr
        .type    updatePtr, @function
    
    // void updatePtr(size_t * ptrA, size_t * ptrB, size_t * val)
    updatePtr:
    .LFB4:
        .cfi_startproc
        pushl    %ebx
        .cfi_def_cfa_offset 8
        .cfi_offset 3, -8
        movl    8(%esp), %ecx
        movl    12(%esp), %eax
        movl    16(%esp), %edx    // 将各地址存在寄存器
        movl    (%edx), %ebx      // 获取*val 存到%ebx备用
        addl    %ebx, (%ecx)      // 这里
        movl    (%edx), %edx      // 再次 获取*val 存到%edx备用
        addl    %edx, (%eax)     // 这里; 都是从val的原始地址现取的值
        popl    %ebx
        .cfi_restore 3
        .cfi_def_cfa_offset 4
        ret
        .cfi_endproc
    2019-07-17 19:20:45
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载