c++: ->运算符的用法 -- 获取结构体和类中元素偏移

->运算符对于指针来说是很常用的,也很方便。

->运算符还可以用于获取结构体元素的偏移。

首先,偏移是什么?

struct Student{
    int  age;

    char  sex;
}

我们定义一个结构体的指针Student *stu = new Student();

如下图: 

对于开辟的Student的空间,其存储结构大致是这样的,stu指针指向这个空间的首地址(也就是第一个属性开始的地址)。
然后,如何找到后面的属性呢?
就是根据偏移。 

首先,Student的首元素为int类型的,所以其第二个元素的偏移值就是sizeof(int) = 4字节; 所以,我们要找到第二个元素,就直接用Student的首地址(指针stu记录的地址)加上4,就可以得到第二个元素的地址了。(这里使用的是Student的指针,如果是直接创建对象也是类型的,变量的地址就是首地址)

获取属性的偏移值

在一些场景下,我们需要获取到数据的偏移值,然后通过其地址找到首地址或者其它的场景下要获取到偏移值。

这里我们使用->运算符获取属性的偏移值。 同样以上面的Student为例子。

(int)&(((Student*)0)->age);     (0也可以用NULL和nullptr来代替)        // 这条语句就可以获取到age在Student类中的偏移值

原理:
(Student*)0 :  表示的是,我们将Student这个类的地址,准确的来说是首地址,看做为0。
                       将0转化为Student*类型。


(int)&(((Student*)0)->age) :  表示的是,我们将0看做Student的首地址之后,使用->运算符去访问age属性,然后对其取地址,获得age的地址,然后转换为int类型方便查看。

因为现在Student的首地址为0,所以获得元素的地址都是前一个元素的类型的字节数+0,也就是其的偏移值。(首元素的为0)

看下面代码:   获取到Vector3中的三个元素的偏移值

struct Vector3 {
	float x, y, z;
};

int main() {
	int offset = (int)&(((Vector3*)0)->x);            // 0可以替 换成NULL或者nullptr
	std::cout << offset << std::endl;                 // 0

	offset = (int)&(((Vector3*)0)->y);				  // 0可以替换成NULL或者nullptr
	std::cout << offset << std::endl;				  // 4

	offset = (int)&(((Vector3*)nullptr)->z);		  // 0可以替换成NULL或者nullptr
	std::cout << offset << std::endl;                 // 8 
}

 问题: 0的地址不是禁止操作的吗?

上面的代码,我们将地址0转换为对应的类,然后去访问内部数据。
但是地址0,(NULL,或者nullptr)不是不允许操作的吗?

其实禁止操作,我们只要不去对0这块地址进行赋值就好了,去访问其元素是允许的。

比如: (Vector3*)0 -> age;  // 这条语句是允许的 

          *((int*)0);                  // 也是允许的                               


 因为我们只是访问,并没有赋值

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值