首页 > 解决方案 > 为什么这种类型的双关语不是未定义的行为?

问题描述

这是一个我认为会调用未定义行为的玩具示例:

#include <cstdint>
#include <iostream>
#include <vector>

int
main()
{
    std::vector<uint16_t> foo = {0, 0x42F6};
    std::cout << *reinterpret_cast<float*>(foo.data()) << std::endl;
    return 0;
}

我很确定取消引用结果reinterpret_cast会违反严格的别名规则。然而:

$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
$ g++ -fstrict-aliasing -Wstrict-aliasing -fsanitize=undefined -std=c++14 -o a a.cpp
$ ./a
123

编译器或 UB sanitizer 没有警告。为什么不?

标签: c++undefined-behaviortype-punning

解决方案


为什么这种类型的双关语不是未定义的行为?

你的前提是错误的。行为未定义

编译器没有警告......为什么不呢?

不需要编译器就 UB 发出警告。有时它会在星星对齐时确实如此,但通常编译器证明 UB 存在的成本高得令人望而却步。事实上,如果有可能,那么语言规则可能会指定程序为非良构程序。

或 UB 消毒剂。为什么不?

UB 消毒剂并不完美。它无法检测到所有 UB。考虑提交功能请求以实现对这种情况的检测 - 假设尚未提出请求。


推荐阅读