据我所知,当两个指针(或引用)没有彼此键入别名时,编译器假设它们处理不同的位置并对其进行某些优化是合法的,例如,重新排序指令。因此,具有指向不同类型的指针以具有相同的值可能是有问题的。但是,我认为这个问题仅适用于将两个指针传递给函数的情况。在创建两个指针的函数体内,编译器应该能够确定它们之间的关系,以确定它们是否在同一位置。我是对的吗?
答案 0 :(得分:3)
据我所知,当两个指针(或引用)没有输入别名时 相互之间,编译器做出假设是合法的 他们处理不同的地点并确定 其优化,例如重新排序指令。
正确。例如,GCC会对此表单执行优化,可以通过传递标记-fno-strict-aliasing
来禁用该表单。
但是,我认为这个问题仅适用于两个指针 传递给函数。函数体内有两个指针 在创建之后,编译器应该能够确保关系 他们之间是否在同一地点。我是对的吗?
标准不区分这些指针的来源。如果您的操作具有未定义的行为,则程序具有未定义的行为,句点。编译器没有义务在编译时分析操作数,但他可能会给你一个警告。
答案 1 :(得分:-1)
经过设计且旨在用于低级编程的实现,在不涉及别名的情况下,认识到一种类型的存储在一种类型的存储被重用或重新解释为另一种的常见模式时,应该没有特别困难,
在任何特定的函数或循环中,用于访问特定存储区的所有指针或左值均来自标识同一数组的相同对象或元素的通用类型的左值,并且
在创建派生类型指针与最后一次使用它或从它派生的任何指针之间,所有涉及存储的操作都只能使用派生指针或从它派生的其他指针来执行。
大多数需要对存储进行重用或重新解释的低级编程方案都符合这些条件,并且在为低级编程设计的实现中,符合这些条件的代码通常很简单。例如,如果某个实现在寄存器中缓存左值并执行循环提升,则只要使用T或T *来形成另一个类型的指针或左值,就可以通过刷新类型T的所有缓存值来合理有效地支持上述语义。这种方法可能是最佳方法,但与完全阻止所有基于类型的优化相比,其性能降低的幅度要小得多。
请注意,即使是打算用于低级编程的实现,尝试处理所有可能涉及别名的情况,在很多情况下也可能不值得。这样做比处理不涉及别名的更为常见的方案要昂贵得多。
当然,不需要专门针对其他目的的实现就可以尝试支持6.5p7的任何例外情况,即使是那些经常被视为标准一部分的例外。这样的实现是否应该能够支持这样的构造将取决于它设计的特定目的。