繁体   English   中英

在c ++类中进行指针数学运算:是“合法”吗?

[英]Doing pointer math in a c++ class: Is it “legit”?

阿海,海,

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

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

只是好奇Dan O

我想从技术上讲它可能会解决。

但是,有几个问题。 酒吧是私人的。 您正在混合使用不同类型的指针(指针算术依赖于指针类型: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);
}

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

它没有任何问题,但是如果您不小心,将非常危险。

另一方面,您的代码是错误的。 (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

您在示例中所做的并不是很好地使用指针。 如果编译器做的事情与您预期的不同,它可能无法正常工作,并且可以使用常规方法以简单,高效,较少的源代码完成它。

如果您有有效的使用,指针算术就没有错。 但是,该语言还没有覆盖很多。

没关系(通常您会为它定义一个宏,例如Windows DDK的CONTAINING_RECORD宏),但是我想问为什么在C ++中需要它? 通常,您在C中使用这些技巧。

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

尽管这看起来太费解并且容易出错,但没有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM