c++ - static_cast 的指针值
问题描述
在当前的标准草案(和 C++17)中,这是关于 static_casting a 的void *
:
“指向cv1 void 的指针”类型的纯右值可以转换为“指向cv2 T 的指针”类型的纯右值,其中 T 是对象类型,而 cv2 与cv1具有相同的 cv 限定或大于cv1的 cv 限定。如果原始指针值表示内存中一个字节的地址A,并且A不满足T的对齐要求,那么得到的指针值是未指定的。否则,如果原始指针值指向对象a,并且存在 T 类型的对象b(忽略 cv 限定)与a指针可互转换,则结果是指向b的指针. 否则,指针值不会因转换而改变。
我想知道,转换是否可以指针互转换有什么区别?有没有一种情况,当将 avoid *
转换为指针可互转换的东西实际上会改变指针值?这种区分的目的是什么?
对于完整性指针可互换:
如果满足以下条件,两个对象 a 和 b 是指针可互转换的:
- (4.1) 它们是同一个对象,或
- (4.2) 一个是联合对象,另一个是该对象的非静态数据成员 ([class.union]),或
- (4.3) 一个是标准布局类对象,另一个是该对象的第一个非静态数据成员,或者,如果该对象没有非静态数据成员,则该对象的任何基类子对象([class.内存]),或
- (4.4) 存在一个对象 c 使得 a 和 c 是指针可互转换的,而 c 和 b 是指针可互转换的。
如果两个对象是指针可互转换的,那么它们具有相同的地址,并且可以通过 reinterpret_cast 从指向另一个对象的指针获得指向其中一个对象的指针。
解决方案
您可能会误解术语“指针值”。该术语在[basic.compound]/3中定义:
指针类型的每个值都是以下之一:
指向对象或函数的指针(该指针被称为指向对象或函数),或
超过对象末尾的指针([expr.add]),或
该类型的空指针值([conv.ptr]),或
无效的指针值。
指针类型的值是指向或超过对象末尾的指针,表示对象占用的内存中第一个字节([intro.memory])的地址或存储结束后内存中的第一个字节分别被物体占据。
所以可以看到标准中的“指针值”这个词是一个很抽象的词。即使两个指针值表示相同的地址,它们也可能具有不同的值。cppreference中的示例很好地展示了“指针值”的概念:
struct S1 { int a; } s1;
struct S2 { int a; private: int b; } s2; // not standard-layout
union U { int a; double b; } u = {0};
int arr[2];
int* p1 = reinterpret_cast<int*>(&s1); // value of p1 is "pointer to s1.a" because s1.a
// and s1 are pointer-interconvertible
int* p2 = reinterpret_cast<int*>(&s2); // value of p2 is unchanged by reinterpret_cast and
// is "pointer to s2".
int* p3 = reinterpret_cast<int*>(&u); // value of p3 is "pointer to u.a": u.a and u are
// pointer-interconvertible
double* p4 = reinterpret_cast<double*>(p3); // value of p4 is "pointer to u.b": u.a and u.b
// are pointer-interconvertible because both
// are pointer-interconvertible with u
int* p5 = reinterpret_cast<int*>(&arr); // value of p5 is unchanged by reinterpret_cast and
// is "pointer to arr"
推荐阅读
- python - 如何在不使用循环或在 Pandas 中迭代(groupby)组的情况下应用可迭代窗口的滚动功能?
- jquery - 如何通过解析 HTML 平台 Node.js 使用 jQuery 准确获取包含的字段
- lua - Roblox 2009 Lua:获取 Loadstring 的错误
- c# - Entity Framework Core 执行多次
- php - 首先使用 NGINX 和 PHP + 用户授权进行文件上传
- java - 如何让任务取消它自己的未来?
- css - 如何在我的网站上跨所有页面检测未使用的 CSS?
- bash - 在 jenkins 配置 shell 中为双引号表达式添加了额外的单引号
- google-cloud-dataflow - 写入步骤完成后流式传输管道发布到 pubsub
- c++ - 使用虚拟变量在循环内切片 std::vector 的最佳方法