1

啊喂喂喂

我想知道是否可以执行以下操作:

class SomeClass
{
   int bar;
};

SomeClass* foo = new SomeClass();
int offset = &(foo->bar) - foo;

SomeClass* another = new SomeClass();
*(another+offset) = 3; // try to set bar to 3

只是好奇,丹奥

4

6 回答 6

11

我想在技术上它可能会奏效。

然而,有几个问题。酒吧是私人的。您正在混合不同类型的指针(指针算术依赖于指针类型: int* + 1 和 char* + 1 具有不同的结果,因为 int 和 char 具有不同的大小)。

您是否还考虑过指向成员的指针:

#include <cassert>

struct SomeClass
{
   int bar;
};

int main() {
    int SomeClass::*mem_ptr = &SomeClass::bar;
    SomeClass foo;
    foo.*mem_ptr = 3;
    assert(foo.bar == 3);
}
于 2009-09-07T18:10:15.313 回答
5

这个想法对于 POD 类来说是可以的(其他人对示例代码中的错误所说的话是一样的)。对于非 POD 类,您不一定仅通过对象指针的偏移量来识别成员。例如,考虑成员是否是基类的一部分,或者等效地,如果您想将偏移量应用于指向派生类的指针,但涉及多重继承或虚拟继承。

但是,您知道指向成员的指针吗?

struct SomeClass
{
    int bar;
};

// fieldtoset is a pointer-to-member
int SomeClass::*fieldtoset = &SomeClass::bar;

SomeClass* another = new SomeClass();
// syntax works as if "*fieldtoset" is "bar" (the member variable referand)
another->*fieldtoset = 3 // set bar to 3
于 2009-09-07T18:11:00.673 回答
1

您在示例中所做的并不是很好地使用指针。如果编译器执行的操作与您预期的不同,它可能无法正常工作,并且可以使用普通方法以同样简单、高效且源代码更少的方式完成。

如果你有一个有效的使用,指针算术没有错。不过,该语言尚未涵盖的内容并不多。

于 2009-09-07T18:12:13.997 回答
1

没有什么不好,但一不小心就很危险。

另一方面,您的代码是错误的。(another+offset) 的指针类型是什么?它实际上是指向 SomeClass 的指针,而不是 int,因此您至少应该将指针转换为 (int *):

 *((int *)(another + offset)) = 3;

偏移量是另一件需要注意的事情,因为它总是以指针指向的类型为单位。简而言之,当int为 4 字节长时,给(int *)指针加 1 实际上会加 4,因此在进行计算之前最好将任何指针强制转换为 (char *)。

所以对于你的例子:

SomeClass* foo = new SomeClass();
int offset = (char *)&(foo->bar) - (char *)foo;

SomeClass* another = new SomeClass();
*((int *)((char *)another+offset)) = 3; // try to set bar to 3
于 2009-09-07T18:04:18.817 回答
0

没关系(通常你会为它定义一个宏,就像 Windows DDK 的 CONTAINING_RECORD 宏一样),但我会质疑为什么你在 C++ 中需要它;通常你会在 C 中使用这些类型的技巧。

于 2009-09-07T18:03:07.400 回答
0

查看原始地址,这似乎可行,但对于您声明中的初学者:int offset = &(foo->bar) - foo;您正在尝试减去不同的指针类型。因此,如果您将它们 reniterpret_cast 转换为 char * 它应该可以为您提供所需的内容。

尽管这似乎太复杂且容易出错而没有任何用处。

于 2009-09-07T18:05:47.207 回答