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

Does type aliasing issue exist only when pointers are passed to functions as arguments?

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

As far as I know, when two pointers (or references) do not type alias each other, it is legal to for the compiler to make the assumption that they address different locations and to make certain optimizations thereof, e.g., reordering instructions.

正确。例如,GCC 确实执行这种形式的优化,可以通过传递标志 -fno-strict-aliasing.

来禁用它

However, I think this issue only applies when the two pointers are passed to functions. Within the function body where the two pointers are created, the compiler should be able to make sure the relationship between them as to whether they address the same location. Am I right?

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

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

  1. 在任何特定的函数或循环中,用于访问特定存储片的所有指针或左值都派生自通用类型的左值,这些左值标识同一对象或同一数组的元素,并且

  2. 在派生类型指针的创建和最后一次使用它或从它派生的任何指针之间,涉及存储的所有操作仅使用派生指针或从它派生的其他指针执行.

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

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

当然,专门用于其他目的的实现不需要做任何尝试来支持 6.5p7 的任何例外——即使是那些通常被视为标准一部分的。这样的实现是否应该能够支持这样的构造将取决于它设计的特定目的。