上次,一个同学问我,你知不知道可以不用引入中间变量就可以实现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=;
*y=;
return *x+*y;// return 7
}
int main () {
int x=,y=;
printf("%d\n",sum(&x,&y));
return ;
}

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

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

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

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

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

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

从花式swap引出的pointer aliasing问题的更多相关文章

  1. 由swap引出的局部变量,形参和指针的小问题

    1.第一种实现swap函数的方法是: swap(int a,int b) { Int c = a;a = b;b =c; } 这表面一看确实是实现了整数a,b的交换,当拿来用时发现,结果并不是我们想要 ...

  2. [翻译]类型双关不好玩:C中使用指针重新解释是坏的

    原文地址 Type punning isn't funny: Using pointers to recast in C is bad. C语言中一个重新解释(reinterpret)数据类型的技巧有 ...

  3. c查漏补缺

    restrict 要理解什么是restrict,首先要知道Pointer aliasing:指两个或以上的指针指向同一数据,例如: ; int *a = &i; int *b = &i ...

  4. 使用freerdp远程连接Windows桌面

    之前使用的是rdesktop,但是由于其不支持NLA认证,便不能登录公司的电脑.为此,现在使用freerdp——这是package的名字,实际的可执行程序是xfreerdp.使用如下的命令行即可实现远 ...

  5. LeetCode 75. Sort Colors(排序颜色)

    Given an array with n objects colored red, white or blue, sort them so that objects of the same colo ...

  6. ”危险“的restrict与GCC的编译优化

    restrict是C99标准中新添加的关键字,对于从C89标准开始起步学习C语言的同学来说(包括我),第一次看到restrict还是相当陌生的.Wikipedia给出的解释如下: In the C p ...

  7. c99标准的restrict关键字

    参考自restrict restrict解释 restrict关键字出现于C99标准,wiki上的解释restrict from wiki. In the C programming language ...

  8. restrict关键字

    值得注意的是,一旦你决定使用restrict来修饰指针,你必须得保证它们之间不会互相重叠,编译器不会替你检查. 关键字restrict有两个读者.一个是编译器,它告诉编译器可以自由地做一些有关优化的假 ...

  9. ”危险“的RESTRICT与GCC的编译优化(编程者对编译器所做的一个“承诺”:使用restrict修饰过的指针,它所指向的内容只能经由该指针修改)

    restrict是C99标准中新添加的关键字,对于从C89标准开始起步学习C语言的同学来说(包括我),第一次看到restrict还是相当陌生的.Wikipedia给出的解释如下: In the C p ...

随机推荐

  1. 一份关于组建.NET Core开源团队的倡议书

    组建这个.NET Core开源团队,旨在为社区出一份力,对自己能力也是一个提升,是一个即利于他人,也利于自己的想法和行动.如果你有很多想法,如果你需要认识更多志同道合的朋友,如果你想展示自己的才华,如 ...

  2. JAVA高级总结

    一.集合框架和泛型 1.集合框架 1) 定义:JAVA API的一部分,用于处理一组长度可变得数据. 2) 和数组的区别: 数组的长度不可变,但是集合框架处理的数据长度可以动态变化. 3) 结构: 接 ...

  3. 文件File

    前面的话 不能直接访问用户计算机中的文件,一直都是Web应用开发中的一大障碍.2000年以前,处理文件的唯一方式就是在表单中加入<input type="file">字 ...

  4. java对象克隆以及深拷贝和浅拷贝

    1.什么是"克隆"? 在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能 会需要一个和A完全相同新对象B,并且此后对B任何改动都不 ...

  5. AOP执行增强-Spring 源码系列(5)

    AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProc ...

  6. PHP语言开发微信公众平台(订阅号)之开启基本功能及获得可用的服务器地址(2)

    1.开启群发功能(单击功能菜单里的"群发功能",并在右侧页面中点击"同意以上声明") 2.(1)在开启开发者模式之前需要完善个人资料(完成头像上传即可) (2) ...

  7. [ZooKeeper.net] 3 ZooKeeper的分布式锁

    基于ZooKeeper的分布式锁 ZooKeeper 里实现分布式锁的基本逻辑: 1.zookeeper中创建一个根节点(Locks),用于后续各个客户端的锁操作. 2.想要获取锁的client都在L ...

  8. Linux块设备驱动(二) _MTD驱动及其用户空间编程

    MTD(Memory Technology Device)即常说的Flash等使用存储芯片的存储设备,MTD子系统对应的是块设备驱动框架中的设备驱动层,可以说,MTD就是针对Flash设备设计的标准化 ...

  9. HTML中的table布局

    <table width="100" height="50" border="1" bgcolor="blue"& ...

  10. windows32位安装MYSQL-python1.2.3

    建议不要用pip安装MYSQL-python,因为会自动选择MYSQL-python1.2.5这个版本,但是这个版本不支持windows 32位系统. 1.首先安装VS2008,因为要依赖VC9.0编 ...