对象占用字节大小 以及利用指针获取对象内部成员数据

1、通过对象指针 访问其内部char* 数据


typedef struct ss{
	const void* mHandle;
	char* mFileName;
};
void tests(){
	ss *ssss = (ss*)malloc(sizeof(ss));
	memset(ssss, 0, sizeof(ss));
	ssss->mFileName = "voiadasdas1213";
	LOGD("-----ttt fileName=%s,%p,%p,%d",ssss->mFileName, ssss, ssss->mFileName, sizeof(ss));
	char* ccp = (char*)*((char**)((u1*)ssss + 4 ));

	LOGD("-----access---%s,%p", ccp, ccp);
	/*ss ssss;
	ssss.mFileName = "voiadasdas1213";
	LOGD("-----ttt fileName=%s,%p,%p,%d",ssss.mFileName, ssss, ssss.mFileName, sizeof(ss));
	char* ccp = *(char**)(((u1*)&ssss + 4 ));*/
}

2、通过对象 指针 访问其int\float基本 数据

class A{
private:
	int a ;
};
//#pragma pack(1)
class B{
public :
	void sss();
	 struct Header {
	      uint8_t magic_[8];
	      uint32_t checksum_;  // See also location
	 };
public:
	A a;
	static const int ll= 999;
	static const int jj= 9199;
	bool b = false;
	unsigned long long g = 60L;
	int qq = 123;
    int cc = 987;
};


int main(int argc,char* argvX[]) {

	B b;
	LOGE("sizeof=%d,%p,%d", sizeof(b), b, sizeof(bool));
	LOGE("acc b=%d,%p", b.qq, &b.qq);
	int* p = (int*)&b;
	LOGE("sizeof=%d",sizeof(bool));
	LOGE("acc 2 b=%d,%p", *((u1*)p+16), p); //p+N ,N取决于数据有没有对齐
	int aaa = *((int*)((u1*)p+16));

	 LOGE("111 size_t=%d", sizeof( unsigned long long));


}

如果对象包含const 的情况:

typedef struct SUB{
    int opt;
    char * s;
    int test;
}SUB;

typedef struct TT{
     size_t num_method_handles_;
     const int call_site_ids_ = 9;
     size_t num_call_site_ids_;
     SUB * sub;
     size_t  end ;
}TT;

int main(int argc,char* argvX[]) {
    TT *t = new TT();
    t->num_method_handles_ = 1;
    //t->call_site_ids_ = 2;
    t->num_call_site_ids_ = 3;
    t->sub = new SUB;
    t->sub->opt = 88;
    t->sub->s = strdup("google");
    t->end = 1080;

    printf("%d,%s\n", t->num_call_site_ids_, t->sub->s);
    int *p = (int*)t;
    (*(int**)(p+3)) = NULL; //将指针置空
    printf("%p\n", t->sub);
    //printf("%s\n", t->sub->s);
    //printf("%d,%s,%d\n", *(p+2), *(*(int**)(p+3) + 1), t->sub->opt);
    //printf("%d\n", *(p+4));

}

 

3、知识讲解

一个Class对象需要占用多大的内存空间。最权威的结论是: 
    *非静态成员变量总合。 
    *加上编译器为了CPU计算,作出的数据对齐处理。 
    *加上为了支持虚函数,产生的额外负担。

介绍完了理论知识后,再看看再找一个例子看看(注:一下所有结果都是在VC6.0 开发环境中得出的结论) 
一、空类的Size

class Car
{
};
 
void main()
{
       int size = 0;
       Car objCar;
       size = sizeof(objCar);
       printf("%s %d /r", "Class Car Size:", size);
}
 
输出结果:Class Car Size:1

这是为何呢?我想对于这个问题,不仅是刚入行不久的开发新手,就算有过几年以上C++开发经验的开发人员也未必能说清楚这个。 
编译器在执行Car objCar;这行代码后需要,作出一个Class Car的Object。并且这个Object的地址还是独一无二的,于是编译器就会给空类创建一个隐含的一个字节的空间。

二、只有成员变量的Size

class Car
{
private:
       int nLength;
       int nWidth;
};
 
void main()
{
       int size = 0;
       Car objCar;
       size = sizeof(objCar);
       printf("%s %d /r", "Class Car Size:", size);
}
 
输出结果:Class Car Size:8

这个结果很多开发人员都清楚。在32位系统中,整型变量占4个字节。这里Class Car中含有两个整型类型的成员变量,所以Class Size是8。

class Car
{
private:
       int nLength;
       int nWidth;
       static int sHigh;
};
 
void main()
{
       int size = 0;
       Car objCar;
       size = sizeof(objCar);
       printf("%s %d /r", "Class Car Size:", size);
}
输出结果:Class Car Size:8

我们这次在Class Car中添加了一个静态成员变量,但是Class Size仍然是8个字节。这正好符合了,结论中的第一条:非静态成员变量总合。

class Car
{
private:
       char chLogo
       int nLength;
       int nWidth;
       static int sHigh;
};
 
void main()
{
       int size = 0;
       Car objCar;
       size = sizeof(objCar);
       printf("%s %d /r", "Class Car Size:", size);
}
输出结果:Class Car Size:12

在类中又插入了一个字符型变量,结果Class Size变成了12。这个就是编译器额外添加3个字符变量,做数据对齐处理,为了是提高CPU的计算速度。编译器额外添加的东西我们是无法看见的。这也符合了结论中的第二条:加上编译器为了CPU计算,作出的数据对齐处理。 
既然,我们这样定义类成员数据编译器会额外的增加空。那么,我们何不在定义类的时候就考虑到数据对齐的问题,可以多定义出3个字符类型变量作为预留变量,既能满足数据对齐的要求,也给自己的程序添加了一些可扩展的空间。

三、只有成员函数的Size

class Car
{
public:
       Car(){};
       ~Car(){};
public:
       void Fun(){};
};
 
void main()
{
       int size = 0;
       Car objCar;
       size = sizeof(objCar);
       printf("%s %d /r", "Class Car Size:", size);
}
输出结果:Class Car Size:1

噢,这是怎么回事儿呢?再做一个实验看看。

class Car
{
public:
       Car(){};
       ~Car(){};
public:
       void Fun(){};
private:
       int nLength;
       int nWidth;
};
 
void main()
{
       int size = 0;
       Car objCar;
       size = sizeof(objCar);
       printf("%s %d /r", "Class Car Size:", size);
}
输出结果:Class Car Size:8

这次应该很清楚的了。函数是不占用类空间的。第一个例子中的Size为1个字节,正是编译器为类创建一个隐含的一个字节的空间

class Car
{
public:
       Car(){};
       virtual ~Car(){};
public:
       void Fun(){};
};
 
void main()
{
       int size = 0;
       Car objCar;
       size = sizeof(objCar);
       printf("%s %d /r", "Class Car Size:", size);
}
输出结果:Class Car Size:4

这次,让析构函数为虚函数,看到了Class Size为4。这正是指向Virtual Table的指针vptr的Size。这正好符合了,结论中的第三条:加上为了支持虚函数,产生的额外负担。

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江西省遂川县常驻深圳大使

喜欢本文,打赏下作者吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值