上次,一个同学问我,你知不知道可以不用引入中间变量就可以实现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. oracle expdp和impdp常用命令选项

    一.expdp导出数据库 1.按用户导出 expdp scott/tiger@orcl DIRECTORY=oracle_dmp dumpfile=bak.dmp schemas=scott vers ...

  2. 队列工厂之(MSMQ)

    最近vs2017神器正式版发布让人很是激动,vs2017支持了很多语言的开发,从前端-后端-底层的支持,堪称是工具中的神器:netcore我喜爱的架构之一也得到了大力的宣传,应群友的邀请将在队列工厂( ...

  3. 1715: [Usaco2006 Dec]Wormholes 虫洞

    1715: [Usaco2006 Dec]Wormholes 虫洞 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 501  Solved: 278[Sub ...

  4. 腾讯云数据库团队:MySQL AHI 实现解析

    MySQL 定位用户记录的过程可以描述为:打开索引 -> 根据索引键值逐层查找 B+ 树 branch 结点 -> 定位到叶子结点,将 cursor 定位到满足条件的 rec 上:如果树高 ...

  5. linux计算程序运行时间

    转自: http://www.cnblogs.com/NeilHappy/archive/2012/12/08/2808417.html #include <sys/time.h> int ...

  6. Spring-Mybatis配置多数据源

    可以参考: http://www.cnblogs.com/ityouknow/p/6102399.html 需要一个DatabaseConfiguration类,实现 TransactionManag ...

  7. 富文本,NSAttributedString,当需要改变的内容有相同的时候的解决方法

    在开发的过程中可能会遇到富文本展示,例如:一行文本,前面是题后面是答案,题和答案用不同的颜色字体,但是答案的内容在题总也有,这时候用平常的方法就会展示错误,因为把题中的内容改变了颜色二实际答案却没有改 ...

  8. SQL AlawaysOn 之五:ISCSI共享磁盘

    用于存放SQL数据库 1.安装服务 2.安装完成后要求重启计算机.添加该功能要配置计算机,如果是正式服务器,那种不能关机太久的服务器,请慎用. 重启之后看到文件和储存服务,击击进去 3.看到ISCSI ...

  9. iOS开发之计算文字尺寸

    /** *  计算文字尺寸 * *  @param text    需要计算尺寸的文字 *  @param font    文字的字体 *  @param maxSize 文字的最大尺寸 */ - ( ...

  10. 自动生成并导出word文档

    今天很荣幸又破解一现实难题:自动生成并导出word文档 先看页面效果: word效果: 代码: 先搭建struts2项目 创建action,并在struts.xml完成注册 <?xml vers ...