码迷,mamicode.com
首页 > 其他好文 > 详细

从花式swap引出的pointer aliasing问题

时间:2016-04-17 17:37:15      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:

上次,一个同学问我,你知不知道可以不用引入中间变量就可以实现swap?

我说,我知道,可以用加减法或者异或实现,像是这样

void mySwap(int &x,int &y) {
    x=x+y;
    y=x-y;
    x=x-y;
}

或者这样

void mySwap(int &x,int &y) {
    x=x^y;
    y=x^y;
    x=x^y;
}

 

但这种花式swap没什么意义,而且具有风险,那就是如果参数引用的是同一个变量,将产生错误的结果0。

这种问题叫pointer aliasing

 

另外C++中也有类似于C语言的restrict关键字,当为参数加上__restrict修饰时,编译器可以据此作出一些编译优化,但是是基于这些指针都是引用不同变量的。如果程序员引用了同样的变量,是undefined behavior(未定义行为)。

 

来看下面所示的代码片段

int sum(int* __restrict x,int* __restrict y) {
    *x=3;
    *y=4;
    return *x+*y;// return 7
}
int main () {
    int x=1,y=2;
    printf("%d\n",sum(&x,&y));
    return 0;
}

 

这代码片段在开不开启编译优化的情况下,都能正确地返回7。

 

当我们不使用变量y,只使用x,并且不开启任何编译优化的情况下,下面的代码片段能够正确地返回8

int sum(int* __restrict x,int* __restrict y) {
    *x=3;
    *y=4;
    return *x+*y;// return 8
}
int main () {
    int x=1;
    printf("%d\n",sum(&x,&x));
    return 0;
}

 

但是当我们在上述代码片段基础上,一旦开启了编译优化(只需-O级),下面的代码片段将错误地返回7

int sum(int* __restrict x,int* __restrict y) {
    *x=3;
    *y=4;
    return *x+*y;// return 7
}
int main () {
    int x=1;
    printf("%d\n",sum(&x,&x));
    return 0;
}

原因很简单,因为编译器根据restrict假设了两个指针指向不同变量,作出了编译优化,在编译阶段便已经知道应当返回7。而我们在实际过程仍然令两个指针指向同一变量,这是未定义行为导致的结果错误。

从花式swap引出的pointer aliasing问题

标签:

原文地址:http://www.cnblogs.com/micrari/p/5401339.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!