代码之家  ›  专栏  ›  技术社区  ›  Lingxi

是否仅当指针作为参数传递给函数时才存在类型别名问题?

  •  2
  • Lingxi  · 技术社区  · 10 年前

    据我所知,当两个指针(或引用)互不类型别名时,编译器可以假设它们寻址不同的位置,并对其进行某些优化,例如重新排序指令。因此,使指向不同类型的指针具有相同的值可能会有问题。然而,我认为这个问题只适用于将两个指针传递给函数的情况。在创建两个指针的函数体中,编译器应该能够确定它们之间的关系,以确定它们是否寻址相同的位置。我说得对吗?

    2 回复  |  直到 10 年前
        1
  •  3
  •   Columbo    10 年前

    据我所知,当两个指针(或引用)不键入别名时 编译器作出假设是合法的 他们解决了不同的地点 其优化,例如重新排序指令。

    对的例如,GCC确实执行了此表单的优化,通过传递标志可以禁用此表单 -fno-strict-aliasing .

    然而,我认为这个问题只适用于两个指针 传递给函数。在函数体中,两个指针 编译器应该能够确保 关于它们是否寻址相同的位置。我说得对吗?

    标准没有区分这些指针的来源。如果操作具有未定义的行为,则程序具有未定义行为,句点。编译器绝对没有义务在编译时分析操作数,但他可能会给你一个警告。

        2
  •  -1
  •   supercat    6 年前

    在不涉及别名的情况下,如果一种类型的存储被重复使用或重新解释为另一种类型,则设计并旨在适用于低级编程的实现在识别常见模式时应该没有特别困难,前提是:

    1. 在任何特定的函数或循环中,用于访问特定存储块的所有指针或lvalues都是从标识相同对象或相同数组元素的公共类型lvalues派生的,并且

    2. 在创建派生类型指针和最后使用派生类型指针或从派生类型指针派生的任何指针之间,所有涉及存储的操作都只能使用派生指针或从该派生类型指针衍生的其他指针来执行。

    大多数需要重用或重新解释存储的低级编程场景都符合这些标准,在为低级编程设计的实现中,处理符合这些标准的代码通常相当简单。例如,如果一个实现在寄存器中缓存lvalues并执行循环提升,那么每当使用T或T*来形成另一种类型的指针或lvalue时,它可以通过刷新T类型的所有缓存值来合理有效地支持上述语义。这样的方法可能是最佳的,但与完全阻止所有基于类型的优化相比,性能降低的程度要小得多。

    请注意,在许多情况下,即使是用于低级编程的实现也可能不值得尝试处理所有可能涉及别名的场景。这样做比处理更常见的不涉及别名的场景要昂贵得多。

    当然,专门用于其他目的的实施不需要做出任何尝试来支持6.5p7的任何例外情况,甚至不需要将其视为标准的一部分。这样的实现是否应该能够支持这样的构造将取决于其设计的特定目的。