C++:reinterpret_cast的奇怪行为
C++: odd behavior with reinterpret_cast
我有以下代码片段
#include <iostream>
using namespace std;
class foobar
{
public:
unsigned int a = 97;
unsigned int b = 98;
unsigned int c = 99;
};
class barfoo
{
public:
char a:32,b:32,c;
};
int main(){
foobar * f = new foobar();
barfoo * b = (reinterpret_cast<barfoo *>(f));
cout << b->a << "-" << b->b << "-" << b->c;
}
输出:
a-b-c
但是,如果我在 barfoo 中指定 c 的宽度,它不起作用(所有值均为 0)。观察
#include <iostream>
using namespace std;
class foobar
{
public:
unsigned int a = 97;
unsigned int b = 98;
unsigned int c = 99;
};
class barfoo
{
public:
char a:32,b:32,c:32;
};
int main(){
foobar * f = new foobar();
barfoo * b = (reinterpret_cast<barfoo *>(f));
cout << b->a << "-" << b->b << "-" << b->c;
}
输出:
--
字符均为 0
知道为什么会这样吗?
链接到 ideone 第一个片段 - 正在工作
Linke to ideone second snippet -- 不起作用
编译器是 gcc-5.1谢谢!!
此reinterpret_cast
不满足已定义行为的要求,因此,虽然其结果的分配是可以接受的,但b
的任何后续访问都是未定义的行为:
barfoo * b = (reinterpret_cast<barfoo *>(f));
reinterpret_cast
必须满足以下条件之一,其中foobar
是动态类型,barfoo
是别名类型:
- AliasedType 是(可能符合 cv 标准的)DynamicType
- AliasedType 和 DynamicType 都是指向同一类型 T 的指针(可能是多级的,可能是每个级别的 cv 合格)。
- AliasedType 是 DynamicType 的(可能符合 cv 标准的)有符号或无符号变体
- AliasedType 是一种聚合类型或联合类型,它将上述类型之一保存为元素或非静态成员(包括递归的子聚合元素和所包含联合的非静态数据成员):这使得在给定指向其非静态成员或元素的指针的情况下,可以安全地获取指向结构或联合的可用指针。
- AliasedType 是 DynamicType 的基类(可能符合 cv 标准)
- AliasedType 是
char
或unsigned char
:这允许检查任何对象的对象表示为无符号字符数组。
由于 AliasedType 不属于任何这些条件,因此访问reinterpret_cast
的结果是未定义的行为。
首先,检查 2 个类的大小是否相同。可以想象,填充和对齐可能会使位域 a、b 和 c 的位置与普通成员 a、b 和 c 等的位置不同。为什么要对 32 位位字段使用 char?我的编译器警告位域超过类型大小。
否则(如果您将 char 更改为 barfoo 类的无符号 int),无论向您抛出任何标准 UB ,reinterpret_cast和访问都有很大的机会工作。如果您通过联合使用得到充分支持和完善的类型双关语的成语,则可能更是如此。
通过联合进行类型双关是一种告诉编译器"这两个不同类型的指针可能会别名,不要进行激进的优化,假设它们可能不会别名"的一种方式。
相关文章:
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++Cast运算符过载
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- C++:"Expected '(' for function-style cast or type construction"错误
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- Shared_ptr cast vs static_cast speed
- C++20 中的严格别名规则是否允许标准 c++ unicode 字符和下划线类型之间"reinterpret
- 在 iOS 上使用 Aruco 构建 OpenCV 时"Functional-style cast from id to double is not allowed"
- 覆盖 CAST 运算符(我认为它被称为向下转换)
- C++错误,隐 <function-style-cast> 式要求使用模板化类一次调用多个构造函数的多个转换
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- C++ C++ 中的函数声明,键入 CAST
- static_cast会丢弃错误,但C风格的演员cast有效
- C++ cast char * to unsigned char
- 禁用 Clang 中的"cast from pointer to smaller type uint32_t"错误
- 是否可以使用gcc 3.3版修复与int*cast相关的Sun Solaris OS 5.8分段故障
- C++ const-cast 一个引用