有效的指向成员的指针是否可以与 NULL 指针具有相同的值?

Can a valid pointer-to-member have the same value as a NULL pointer?

根据ABI

A pointer to data member is an offset from the base address of the class object containing it... A NULL pointer is represented as -1

但是,根据 c++ 标准(我有修订版 4296,它在 4.11/1 中),

the null member pointer value of that type ... is distinguishable from any pointer to member not created from a null pointer constant

-1 可以是有效的偏移量。

考虑这种情况:

#include <iostream>
using namespace std;

struct A {
    char a,b,c,d,e,f,g,h;
};

struct B {
    int i;
};

struct C : A,B {};

int main() {
    char C::*p=&C::h;
    char B::*q = static_cast<char B::*>(p);
    cout<< (q==nullptr) <<endl; //prints 1
}

在这段代码中,我的编译器(x86_64-linux-gnu 上的 g++4.9.2)将 h 放在 A 的最后一个字节,并将 B 放在在 C 中的 A 之后。因此,C::A::h相对于C::B的基地址的偏移量是-1。

(转换是合法的,其结果可以用在动态类型C的对象上,即使它的静态类型是B。标准说(5.2.9/12) "although class B need not contain the original member, the dynamic type of the object with which indirection through the pointer to member is performed must contain the original member")

我误会了什么?

(我怀疑我的误解是关于短语 "the class containing the original member" (5.2.9/12) - 考虑到 C::h,该短语可能指的是A 而不是 C,但标准明确表示 (10/2) "members of a base class are also considered to be members of the derived class")

[expr.static.cast]/p12:

A prvalue of type “pointer to member of D of type cv1 T” can be converted to a prvalue of type “pointer to member of B” of type cv2 T, where B is a base class (Clause 10) of D, [...]. If class B contains the original member, or is a base or derived class of the class containing the original member, the resulting pointer to member points to the original member. Otherwise, the behavior is undefined.

"class containing the original member" 是 AB 不是 A 的基础或派生 class,因此行为未定义。

你错了,从 base 地址偏移 -1 是不可能的。对象的基地址是完整对象的地址,而不是该完整对象中子对象的地址。