是否将两个void指针与C++中定义的不同对象进行比较?

Mar*_* Ba 14 c++ comparison void-pointers language-lawyer

灵感来自这个关于动态演员的答案void*:

...
bool eqdc(B* b1, B *b2) {
    return dynamic_cast<void*>(b1) == dynamic_cast<void*>(b2);
}
...
int main() {
    DD *dd = new DD();
    D1 *d1 = dynamic_cast<D1*>(dd);
    D2 *d2 = dynamic_cast<D2*>(dd);
    ... eqdc(d1, d2) ...
Run Code Online (Sandbox Code Playgroud)

如果完全定义使用C++的行为(根据03或11个标准),以我想知道比较的(中)相等对两个空指针指向有效的,但不同的对象.

更一般地说,但可能不那么相关,是比较(==!=)两个void*总是定义的类型的值,还是要求它们持有指向有效对象/存储区域的指针?

Kos*_*Kos 12

C说:

两个指针比较相等,当且仅当两个都是空指针时,两者都是指向同一对象的指针(包括指向对象的指针和开头的子对象)或函数,两者都是指向同一数组的最后一个元素的指针对象,或者一个是指向一个数组对象末尾的指针,另一个是指向不同数组对象的开头的指针,该对象恰好跟随地址空间中的第一个数组对象.

C++说:

相同类型的两个指针比较相等,当且仅当它们都为空时,都指向相同的函数,或者两者都表示相同的地址.

因此,这意味着:

一个)

它是C++中完全定义的行为(根据03或11标准)来比较两个指向有效但不同对象的(in)相等的void指针.

所以是的,在C和C++中.您可以比较它们,在这种情况下,如果它们指向同一个对象,它们将比较为真.这很简单.

b)

是比较(==或!=)两个类型为void*总是定义的值,还是要求它们持有指向有效对象/内存区域的指针?

同样,比较是明确定义的(标准说"当且仅当"因此两个指针的每个比较都是明确定义的).但是之后...

  • C++谈论"地址",所以我认为这意味着标准要求它"按照我们的预期"工作,
  • 但是,C要求指针既可以为null,也可以指向对象或函数,或指向数组对象之后的一个元素.如果我的阅读技巧没有关闭,这意味着如果在给定的平台上你有两个具有相同值的指针,但没有指向有效的对象(例如未对齐),那么比较它们应该是明确定义的并且产生错误.

这太令人惊讶了!

的确,这不是GCC的工作方式:

int main() {
    void* a = (void*)1; // misaligned, can't point to a valid object
    void* b = a;
    printf((a == b) ? "equal" : "not equal");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

结果:

equal
Run Code Online (Sandbox Code Playgroud)

也许在C中的UB有一个不是空指针的指针,并且没有指向一个对象,子对象或一个超过数组中最后一个对象的指针?嗯...这是我的猜测,但后来我们有了:

整数可以转换为anypointer类型.除了之前指定的,结果是实现定义,可能未正确对齐,可能不指向引用类型的实体,并且可能是陷阱表示.

所以我只能解释它上面的程序定义明确,C标准期望它打印"不相等",而GCC并没有真正服从标准,而是提供了更直观的结果.

  • "未对齐,不能指向有效对象"是错误的,因为它**理论上可以指向`char`对象.实际上它并没有指向一个对象,至少在用户模式下没有指向(比如说)linux,但我认为我们不应该从C中读出这句话,因为指针的`==`运算符应该以某种方式检测地址当前是否有效.相反,我认为有效的程序首先不使用无效地址,这已经不言而喻(实际上已在其他地方说过了). (3认同)