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的理解有误,或者需要在编译时加入特定选项?谢谢回答。
你对于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
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。