C++ 中的指针别名

问题描述 投票:0回答:1

仅供参考,尝试理解本文

中的示例

总结如下:

int foo(int *a, long *b)
{
    int t = *a;
    *b = 0;          // cannot change *a
    return *a - t;   // can be folded to zero
}

int bar(int *a, long *b)
{
    int t = *a;
    for (int i = 0; i != sizeof *b; ++i)
    ((unsigned char*)b)[i] = 0;
    
    return *a - t;   // must not be folded
}

文章声称 foo 的返回可以被折叠,因为

因为 a 和 b 被声明为指向不兼容类型的指针,并且因为 C 和 C++ 要求对象的存储值只能由兼容类型的左值访问,所以对 *b 的存储不能影响缓存在 *a 中的值变量 t

...但我不明白为什么酒吧里有什么不同。什么代码/事件序列会使折叠无效?

c++
1个回答
0
投票
  • foo
    中,赋值
    *b = 0
    不会影响
    *a
    ,因为在严格的别名规则下,类型是不兼容的。这使得编译器可以安全地将
    *a - t
    折叠为零。
  • 然而,在 bar 中,将 b 转换为
    unsigned char*
    并逐字节写入意味着编译器必须考虑到
    *a
    在循环中被修改的可能性。因此,不能假设
    *a - t
    的值为零,编译器必须避免折叠该表达式。

关键区别在于

unsigned char*
是一种绕过严格别名规则的特殊类型,允许通过
int
间接修改
a
指向的
b
对象。

© www.soinside.com 2019 - 2024. All rights reserved.