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

发布于 2025-01-19 15:14:16 字数 1223 浏览 0 评论 0原文

根据 ABI

指向数据成员的指针是相对于数据成员基地址的偏移量 包含它的类对象... NULL 指针表示为 -1

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

该类型的空成员指针值...是可区分的 从任何指向不是从空指针常量创建的成员的指针

,-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)“尽管 B 类需要不包含原始成员,通过指向成员的指针执行间接操作的对象的动态类型必须包含原始成员”)

我有什么误解?

(我怀疑我的误解是关于短语“包含原始成员的类”(5.2.9/12) - 考虑到 C::h,该短语可能指的是到 A 而不是 C,但标准明确指出 (10/2)“基类的成员也被视为成员派生类的”)

According to 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

However, according to the c++ standard (I have revision 4296, and there it's in 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

and -1 can be a valid offset.

Consider this situation:

#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
}

In this code, my compiler (g++4.9.2 on x86_64-linux-gnu), places h at the last byte of A, and places B right after A in C. Hence, the offset of C::A::h from the base address of C::B is -1.

(The conversion is legal, and its result can be used on an object of dynamic type C, even if its static type is B. The standard says (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")

What am I misunderstanding?

(I suspect that my misunderstanding is about the phrase "the class containing the original member" (5.2.9/12) - considering C::h, that phrase may refer to A and not to C, but the standard explicitly says (10/2) "members of a base class are also considered to be members of the derived class")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半葬歌 2025-01-26 15:14:16

[expr.static.cast]/p12:

可以将类型的“指向d cv1 t的指针”转换为类型“指向b 成员的指针” /代码>”类型CV2
t,其中bd的基类(第10条),[...]。如果类b包含原始成员,则是基础或
衍生的
包含原始成员的类的类
指向会员指向原始成员。否则,
行为不确定。


“包含原始成员的类”是ab不是a的基础或派生类,因此该行为不确定。

[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.

The "class containing the original member" is A. B is not a base or derived class of A, so the behavior is undefined.

や三分注定 2025-01-26 15:14:16

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

You're wrong, an offset of -1 from the base address is impossible. The base address of an object is the address of the full object, and not that off a subobject within that full object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文