考虑:
struct T{};
int main() {
T* p = (T*)0xDEADBEEF;
}
使用无效指针是实现定义的。取消引用它是未定义的行为。我的问题不在于那些。
我的问题是,p
的初始化是否已定义。
如果您认为已经拥有回答此问题所需的所有信息(或者如果您发现这是重复的),则无需进一步阅读。根据我的发现,以下是一些谦虚:
C标准(C ++标准所基于的)说:
6.3.2.3指针
5 整数可以转换为任何指针类型。除非事先指明,否则 结果是实现定义的,可能没有正确对齐,可能不指向 引用类型的实体,可能是陷阱表示。
提示它可能是实现定义的。
C ++标准仅定义(据我所知),无效指针值的任何使用都是实现定义的。脚注特别重要,因为它似乎表明仅仅 copy 这样的值已经是指针的使用。 (或者它是否意味着指向值?我很困惑)
6.7存储时间
4 当达到存储区域的持续时间结束时,表示该存储区域任何部分地址的所有指针的值将变为无效指针值(6.9.2) 。通过无效指针值间接并将无效指针值传递给释放函数具有未定义的行为。对无效指针值的任何其他使用都具有实现定义的行为。 37
37某些实现可能会定义复制无效指针值会导致系统生成的运行时故障
这种符合C标准。问题是我不相信这是无效指针值的一个例子,因为标准清楚地说这种类型的值是由达到该地址的存储持续时间的结束引起的(这显然从未发生过。)
未定义行为 TM 的许多指针算法实例,但显然没有算术或在这里完成对指针值的操作。这只是一个初始化。
答案 0 :(得分:4)
你的C风格演员正在表演reinterpret_cast
;像这样输出任意整数值是implementation-defined:
8.5.1.10重新解释演员表
5可以将整数类型或枚举类型的值显式转换为指针。转换为足够大小的整数(如果实现上存在任何此类)并返回相同指针类型的指针将具有其原始值;指针和整数之间的映射在其他方面是实现定义的。 [注意:除[basic.stc.dynamic.safety]中所述之外,此类转换的结果不是安全派生的指针值。 - 结束记录]
如果结果是(被实现认为是)无效的指针值,那么它可能会再次implementation-defined当它存储在变量中时会发生什么,但那不太清楚:
6.6.4存储持续时间
4当达到存储区域的持续时间结束时,表示该存储区域的任何部分的地址的所有指针的值变为invalid pointer values。 通过无效指针值间接并将无效指针值传递给释放函数具有未定义的行为。 对无效指针值的任何其他使用都具有实现定义的行为。
答案 1 :(得分:1)
根据我对桌面(UNIX,Linux,Windows)应用程序的经验,我认为您可以为指针分配任何值。如果您没有取消引用指针,那么当您将这些值分配给指针时,这些系统不会引起奇怪的行为。
以下示例显示了我看到的一种机制,用于处理保存指向磁盘的指针以及从磁盘恢复指针。
让我们简单了解CAD模型的面,边和顶点之间的连接。
struct Face;
struct Edge;
struct Vertex;
struct Face
{
std::vector<Edge*> edges;
};
struct Edge
{
std::vector<Face*> faces;
Vertex* start;
Vertex* end;
};
struct Vertex
{
std::vector<Edge*> edges;
double x;
double y;
double z;
};
你在XY平面上有一张脸。
E3
V4 +--------+ V3
| |
E4 | F | E2
| |
+--------+
V1 E1 V2
可以使用以下格式将这样的面部保存到磁盘。
0 Face 4 $1 $2 $3 $4
1 Edge 1 $0 $5 $6
2 Edge 1 $0 $6 $7
3 Edge 1 $0 $7 $8
4 Edge 1 $0 $8 $5
5 Vertex 2 $1 $4 0 0 0
6 Vertex 2 $2 $1 10 0 0
7 Vertex 2 $3 $2 10 10 0
8 Vertex 2 $4 $3 0 10 0
其中第一个数字表示对象数组中的索引,而具有$
前缀的字段是指向该索引处项目的指针。
从磁盘读取该信息时,有两次将对象恢复到可用状态。在第一遍中,索引被存储在指针的位置。在第二遍中,索引被转换为指针。在第一遍中,数字[0
- 8
]存储在指向预期的位置。只有在第二次传递之后,指针才会指向适当的对象。
长篇排序,指针成员变量被赋予显然不是有效指针的值,但机制可以完美运行。
对于其他平台是否会出现问题,我无法发表评论。我没有经验可以依靠。