是否增加了一个明确定义的空指针?

Luc*_*ore 47 c++ pointers language-lawyer

在执行指针算术时有很多未定义/未指定行为的示例 - 指针必须指向同一个数组(或者一个超过结尾),或者在同一个对象内,限制何时可以根据上述进行比较/操作等

以下操作定义明确吗?

int* p = 0;
p++;
Run Code Online (Sandbox Code Playgroud)

Col*_*mbo 36

§5.2.6/ 1:

1除非对象的类型为bool[..] ,否则操作数对象的值将通过添加来修改.

涉及指针的附加表达式在第5.7/5节中定义:

如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义.

  • 我很好奇标准中如何定义"数组对象".`malloc`的返回值是否被视为数组对象? (6认同)

gna*_*729 15

对"未定义行为"的含义似乎很少了解.

在C,C++和Objective-C等相关语言中,有四种行为:存在由语言标准定义的行为.存在实现定义的行为,这意味着语言标准明确表示实现必须定义行为.存在未指定的行为,其中语言标准表示可能存在多种行为.并且存在未定义的行为,其中语言标准没有说明结果.因为语言标准没有说明结果,所以任何事情都可能发生在未定义的行为上.

这里的一些人认为"未定义的行为"意味着"发生了不好的事情".那是错的.这意味着"任何事情都可能发生",其中包括"可能发生的坏事",而不是"必须发生的事情".在实践中,它意味着"当你测试你的程序时没有什么不好的事情发生,但是一旦它被发送给客户,一切都会崩溃".由于任何事情都可能发生,编译器实际上可以假设代码中没有未定义的行为 - 因为它是真的,或者它是假的,在这种情况下任何事情都可能发生,这意味着由于编译器的错误假设仍然发生正确.

有人声称,当p指向3个元素的数组,并计算p + 4时,不会发生任何不良事件.错误.这是你的优化编译器.说这是你的代码:

int f (int x)
{
    int a [3], b [4];
    int* p = (x == 0 ? &a [0] : &b [0]);
    p + 4;
    return x == 0 ? 0 : 1000000 / x;
}
Run Code Online (Sandbox Code Playgroud)

如果p指向a [0],则评估p + 4是未定义的行为,但如果指向b [0]则不是.因此允许编译器假设p指向b [0].因此允许编译器假设x!= 0,因为x == 0导致未定义的行为.因此,允许编译器在return语句中删除x == 0检查,并返回1000000/x.这意味着当您调用f(0)而不是返回0时,程序会崩溃.

另一个假设是,如果你增加一个空指针然后再次递减它,结果再次是一个空指针.又错了.除了增加空指针可能只是在某些硬件上崩溃的可能性之外,接下来是这样的:由于递增空指针是未定义的行为,编译器检查指针是否为空并且只有在指针不是空指针时才递增指针,所以p + 1再次是一个空指针.通常它会对递减执行相同的操作,但作为一个聪明的编译器,它注意到如果结果是空指针,p + 1总是未定义的行为,因此可以假设p + 1不是空指针,因此可以省略空指针检查.这意味着,如果p是空指针,则(p + 1) - 1不是空指针.

  • 这个咆哮甚至没有试图解决这个问题 - 啊 - 它叫什么...哦是的 - ***问题***,这是***不是****"怎么可能未定义的行为显示"*,但问题中的代码是否具有未定义的行为.(公平地说,它确实最终达成了一个讨论,即在没有说明或证明这样做的情况下增加一个未定义的空指针的前提*.这个答案将更好地转移到一个适当的问题.... (4认同)

Pet*_*ter 13

指针的操作(如递增,添加等)通常仅在指针的初始值和结果指向同一数组的元素(或指向最后一个元素的一个元素)时才有效.否则结果是未定义的.各种运营商在标准中都有各种条款,包括增量和增加.

(有一些例外,例如将0添加到NULL或从NULL中减去零是有效的,但这不适用于此).

NULL指针不指向任何内容,因此递增它会给出未定义的行为("otherwise"子句适用).

  • 它们可以指向一个对象,也可以指向一个字节. (2认同)
  • 你说的对C来说是正确的,但对于C++来说却不是这样,Marc.C++ 98的第一句 - 第5.7节第8段说"如果将值0添加到指针值或从指针值中减去,则结果将比较等于原始指针值." (我现在没有更多最新版本的C++标准来检查部分编号).Andrew Koenig的一篇文章讨论了为什么,http://www.drdobbs.com/cpp/why-does-c-allow-arithmetic-on-null-poin/240001022 (2认同)