严格别名违规

6

以下代码是否违反了严格别名规则?

#include <cstdint>

int main()
{
    double d = 0.1;

    //std::int64_t n = *reinterpret_cast<std::int64_t*>(&d); // aliasing violation

    //auto n{*reinterpret_cast<std::int64_t*>(&d)}; // aliasing violation

    auto nptr{reinterpret_cast<std::int64_t*>(&d)};
    auto& n{*nptr};

    ++n;
}

在VS2015、clanggcc中都没有发出任何警告。

2个回答

5

是的,这违反了严格别名规则。你正在访问一个类型为double的对象d,但指针nptr不是指向double或任何相关类型的指针。

仅仅因为编译器没有发出警告并不意味着它不是一种违规行为。违反严格别名规则的行为是UB(因为它们是运行时行为),因此不需要诊断。


关于“严格别名”的违规行为并不是UB(未定义行为)。严格别名是gcc优化相关的概念。相反,C++标准则有关于如何以可移植的方式使用(或不使用)重新解释结果的规则。在这个例子中,这会导致形式上的UB。但是,在特定平台上,这个例子可能是好的。 - Cheers and hth. - Alf
1
@Cheersandhth.-Alf: "C++标准有规定重新解释的结果如何以可移植的方式使用(或不使用)”,这些规则通常被称为“严格别名规则”;这个术语可能源于GCC选项,但规则本身并不是。因此,我不明白你的观点是什么。不,这个例子在任何平台上都不允许定义良好的行为。3.10/10不能让你通过int64_1指针访问double的值。 - Nicol Bolas
C和C++在特定平台上无法进行类型转换的观点与现实相反。因此,这种回应是我试图指出的一个很好的例子。不幸的是,这种观点使得g++(以及作为插件替代品的clang)比它本来可以做到的更少实用。 - Cheers and hth. - Alf
1
@Cheersandhth.-Alf: "认为特定平台上C和C++无法进行类型转换的观点与现实相反。" 这根本不是所谓的"观点"。 "观点"是C++标准不保护它。如果您想依赖于类型转换,那没问题; 您只是依赖于未定义的行为。如果您想这样做,那没问题。但是,您不能假装标准没有将其声明为UB。 - Nicol Bolas

5
以下程序是否违反了严格别名规则?
是的,它违反了。您正在使用std :: int64_t *解引用double *(&d)。
违反严格别名规则的行是:
auto& n{*nptr};

在处理这行代码时,编译器不一定知道您如何设置 nptr 的值。它是一个指向 double* 类型的别名,在处理该行时并不容易看出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接