代码之家  ›  专栏  ›  技术社区  ›  Not a real meerkat

初始化指针时是否定义了任意的、文字的、非零值?

  •  2
  • Not a real meerkat  · 技术社区  · 6 年前

    考虑:

    struct T{};
    
    int main() {
        T* p = (T*)0xDEADBEEF;
    }
    

    使用无效指针是 定义的实现 . 取消引用它是 未定义的行为 . 我的问题不是关于那些。

    我的问题是 p 按原样定义。

    . 以下是根据我的调查结果得出的一些含糊不清的结论:

    C标准(其中C++标准是基于标准)表示:

    6.3.2.3指针

    整数可以转换为任何指针类型。除非前面另有规定,否则 结果是定义了实现,可能没有正确对齐,可能没有指向 引用类型的实体,可能是陷阱表示。

    哪些提示可能是实现定义的。

    C++标准仅定义(据我所知)任何使用 指针值无效 是否定义了实现。脚注特别重要,因为它似乎表明 复制 已经使用了指针。(或者是指指向值?我很困惑)

    6.7储存期限

    当达到存储区域的持续时间结束时,表示该存储区域任何部分地址的所有指针的值将变为无效的指针值(6.9.2)。通过无效的指针值进行间接寻址并将无效的指针值传递给释放函数具有未定义的行为。无效指针值的任何其他使用都具有实现定义的行为。 三十七

    37有些实现可能定义复制无效的指针值会导致系统生成运行时错误

    这符合C标准。问题是我不相信这是一个 指针值无效 ,正如标准明确指出的那样,这种类型的值是由于到达该地址的存储时间结束(显然从未发生过)造成的。

    还有 许多的 指针算术的实例 未定义的行为 TM 但显然,这里没有对指针值进行算术或操作。这只是初始化。

    2 回复  |  直到 6 年前
        1
  •  4
  •   Not a real meerkat    6 年前

    你的C型演员正在表演 reinterpret_cast ;像这样强制转换任意整数值 implementation-defined :

    8.5.1.10重新解释铸造

    5 整型或枚举型的值可以显式转换为指针。转换为足够大小的整数(如果实现中存在此类整数)并返回到同一指针类型的指针将具有其原始值;否则将定义指针和整数之间的映射。[ 注: 除非如中所述 [basic.stc.dynamic.safety] ,这种转换的结果将不是安全派生的指针值。 尾注 ]

    如果结果(被实现视为)是一个无效的指针值,那么它可能会再次出现。 implementation-defined 当它存储在变量中时会发生什么,但不太清楚:

    6.6.4储存时间

    4 当达到存储区域的持续时间结束时,表示该存储区域任何部分的地址的所有指针的值将变为 invalid pointer values . 通过无效的指针值进行间接寻址并将无效的指针值传递给释放函数具有未定义的行为。 无效指针值的任何其他使用都具有实现定义的行为。

        2
  •  1
  •   R Sahu    6 年前

    根据我对桌面(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 ]存储在需要指针的位置。只有在第二次传递之后,指针才会指向适当的对象。

    说来话长,指针成员变量被分配的值显然不是有效的指针,但机制工作得很完美。

    对于其他平台来说,这是否是个问题,我无法置评。我没有经验可以依靠。