受到this answer的启发,关于动态广告投放到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) ...
我想知道它是否是在C ++中完全定义的行为(根据03或11标准)比较两个指向
更一般地说,但可能不那么相关,比较(==
或!=
)两个始终定义的类型void*
的值,或者是否需要它们指向一个指针有效的对象/内存区域?
答案 0 :(得分:11)
两个指针比较相等,当且仅当两个都是空指针时,两个指针都指向 相同的对象(包括指向对象和开头的子对象的指针)或函数, 两者都是指向同一个数组对象的最后一个元素之后的指针,或者一个是指针 到一个数组对象的末尾,另一个是指向另一个数组对象的开头的指针 碰巧紧跟地址中第一个数组对象的数组对象 空间。
C ++说:
相同类型的两个指针比较等于if 并且只有当它们都为空时,都指向相同的函数,或者两者都代表相同的地址。
因此意味着:
A)
它是C ++中完全定义的行为(根据03或11标准)来比较两个指向有效但不同对象的(in)相等的void指针。
所以是的,在C和C ++中。您可以比较它们,在这种情况下,如果它们指向同一个对象,它们将比较为真。这很简单。
b)中
是比较(==或!=)两个类型为void *总是定义的值,还是要求它们保存指向有效对象/内存区域的指针?
同样,比较是明确定义的(标准说“当且仅当”因此两个指针的每个比较都是明确定义的)。但是......然后......
这太令人惊讶了!
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;
}
结果:
equal
也许在C中的UB有一个不是空指针的指针,并且没有指向一个对象,子对象或一个超过数组中最后一个对象的指针?嗯...这是我的猜测,但后来我们有了:
整数可以转换为anypointer类型。除了之前的具体说明, 结果是实现定义,可能没有正确对齐,可能不指向 引用类型的实体,可能是陷阱表示。
所以我只能解释它上面的程序定义明确,C标准期望它打印“不相等”,而GCC并没有真正服从标准,而是提供更直观的结果。
答案 1 :(得分:3)
C ++ 11,5.10 / 1:
可以比较相同类型的指针(指针转换后) 为了平等。相同类型的两个指针比较等于if和only 如果它们都为null,则指向相同的函数,或两者都指向 代表相同的地址
所以是的,具体的比较是可以的。
一般来说,尝试创建一个非有效地址的指针值是未定义的行为 - 例如使用指针算法在数组的开头之前或之后进行 - 更不用说了使用它们。像(void*)23
之类的东西的结果是实现定义的,因此除了实现的特定权限之外,它实际上也是未定义的行为来比较它们,因为实现可能会定义结果是陷阱值{{1} }。