【发布时间】:2019-01-29 18:12:42
【问题描述】:
我试图在违反严格的别名规则时掌握未定义的行为。为了理解它,我已经阅读了很多关于 SO 的文章。但是,仍然存在一个问题:我真的不明白两种类型何时非法别名。 cpp-reference 状态:
类型别名
每当尝试通过 AliasedType 类型的 glvalue 读取或修改 DynamicType 类型的对象的存储值时,除非满足以下条件之一,否则该行为是未定义的:
- AliasedType 和 DynamicType 相似。
- AliasedType 是 DynamicType 的(可能是 cv 限定的)有符号或无符号变体。
- AliasedType 是 std::byte、(C++17 起)char 或 unsigned char:这允许将任何对象的对象表示检查为字节数组。
我还发现了一个nice example on SO,我清楚地看到了这个问题:
int foo( float *f, int *i ) {
*i = 1;
*f = 0.f;
return *i;
}
int main() {
int x = 0;
std::cout << x << "\n"; // Expect 0
x = foo(reinterpret_cast<float*>(&x), &x);
std::cout << x << "\n"; // Expect 0?
}
int 和 float 是不相似的类型,这个程序可能会造成严重破坏。我没有看到和理解的是以下修改:
struct A
{
int a;
};
struct B
{
int b;
};
A foo( A *a, B *b ) {
a->a = 1;
b->b = 0;
return *a;
}
int main() {
A a;
a.a = 0;
std::cout << a.a << "\n"; // Expect 0
a = foo(&a, reinterpret_cast<B*>(&a));
std::cout << a.a << "\n"; // Expect 0?
}
A 和 B 是相似的类型,一切都很好,或者它们是非法别名,我有未定义的行为。如果它是合法的,这是因为 A 和 B 是聚合的(如果是,我需要改变什么才能使其成为未定义行为)?
任何提示和帮助将不胜感激。
EDIT 关于重复的问题
我知道this 的帖子,但我没有看到他们在哪里阐明了哪些类型是相似的。至少没有达到我能理解的程度。因此,如果您不关闭此问题,那就太好了。
【问题讨论】:
-
这是非法的。
A和B是不相关的类型。 -
"...A 和 B 兼容类型...": 否
-
@RichardCritten 我不明白您为什么将问题标记为重复,因为当两种类型兼容时,另一个并没有真正尝试明确,这是这个问题的主要问题。我是否再次无法理解重要的事情?
-
C类型参考文档 "Compatible types" en.cppreference.com/w/c/language/type ;C++文档没有 en.cppreference.com/w/cpp/language/type 。所以 Compatible Types 与C++无关,重复的链接解释了其他所有内容。在什么是对象以及如何操作/引用它的这一领域中,C和C++之间存在显着差异。混合使用 2 个标准中的术语可能会导致混淆。
标签: c++ language-lawyer strict-aliasing type-punning