weixin_45772493 2024-09-28 17:41 采纳率: 100%
浏览 4
已采纳

Pointer aliasing相关问题

img

Pointer aliasing ,简单来说,下面两段代码并不是等价的:

void f1(int* x, int* y) {
    *x += *y;
  *x += *y;
}
void f2(int* x, int* y) {
    *x += 2*(*y);
}

这是因为,x 和 y 两个指针可能指向相同的内存。考虑 f(x, x),第一段代码将把 *x 变为 4(*x),而第二段代码则会把 *x 变为 3(*x)。

Pointer aliasing 可能会抑制编译器做出某些优化。比如在上面的代码中,f1() 需要 5 次访存而 f2() 仅需三次,后者更优。但由于编译器并不能假设 x 和 y ,它不敢做这个优化。

Q: 为什么第一段代码是5次访存,第二段代码是3次?为啥说“不敢”做这个优化,即使做了这个优化,f所造成的结果不一样,优化不是错的吗?还是说就是因为两次优化结果不一样,才让编译器“不敢”做这个优化呢?

  • 写回答

1条回答 默认 最新

  • 一轮明月照丘壑 2024-09-28 17:42
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    首先,我们先来理解什么是pointer aliasing(指针别名)。简单来说,指针别名就是指两个或多个指针指向同一内存位置的情况。这种情况下,修改一个指针指向的值会影响到另一个指针的值。所以,即使我们以为两个指针是相互独立的,但在实际操作时可能并非如此。在编写涉及指针的代码时,需要考虑这种可能性。

    关于你提到的两段代码:

    第一段代码:f1 函数中对同一个内存位置 *x 连续两次执行加法操作。假设 xy 指向同一个地址(即 x == y),那么第一次执行 *x += *y 后,该地址的值增加了一次 *y 的值,第二次再执行相同的操作,该地址的值再次增加一次 *y 的值。所以总共是两次加法操作,但每次加法操作都需要访问内存一次,所以总共是两次访存操作。因此,对于 f1 函数来说,总共是 5 次访存(两次加法操作需要各访问一次内存)。

    第二段代码:f2 函数对同一个内存位置执行了一次加法操作(实际是一个复合操作,可以视为两个加法操作的组合)。由于指针别名问题存在不确定性,如果假设 xy 不指向同一个地址,那么这个操作就是正常的。但如果它们指向同一个地址,那么结果就会与预期不同(因为涉及到乘法和加法组合)。因此,编译器无法确定应该优化为更少的访存操作而不产生副作用或不确定的行为。这就是为什么编译器“不敢”做这个优化。即使这样做可能提高性能(在某些情况下),但由于潜在的不确定性,编译器宁愿保持原样。这确保了程序的正确性和稳定性。

    总结来说,pointer aliasing 可能导致编译器在处理涉及指针的代码时面临不确定性。由于这种不确定性可能导致不可预测的行为或副作用,编译器通常会避免进行可能导致不确定结果的优化。这也是为什么在某些情况下,即使优化可能提高效率,编译器也可能选择不进行这种优化的原因。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 今天
  • 创建了问题 9月28日

悬赏问题

  • ¥15 35114 SVAC视频验签的问题
  • ¥15 impedancepy
  • ¥15 在虚拟机环境下完成以下,要求截图!
  • ¥15 求往届大挑得奖作品(ppt…)
  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图
  • ¥15 UE5.1局部变量对蓝图不可见