`
jiq408694711
  • 浏览: 33646 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

C++中结构体的sizeof

 
阅读更多
  • 为什么要地址对齐?
  • * 我们在访问内存时,如果地址是按4字节对齐,则访问效率会高很多。
  • * 这个问题的原因在于访问内存的硬件电路。一般情况下,地址总线总是按照对齐后的地址来访问。
  • * 例如你想得到0x00000001开始的4字节内容,系统首先需要以0x00000000读4字节,
  • * 然后从中取得3字节,然后在用0x00000004作为开始地址,获得下一个四字节,
  • * 在从中得到第一个字节,两次组合出你想得到的内容。但是如果地址一开始就是对齐到
  • * 0x00000000,则系统只要一次读写即可。
  • 所以,为了性能考虑,编译器会做地址对齐。
  • 地址对齐的原则:
  • 每个基本类型有自己默认的对齐值。 然后可以通过#pragma pack(2)设置编译器的默认对齐值。取两者最小的一个作为最终对齐值。
  • 若没有#pragma pack(2)设置,那么只看基本类型自己的对齐值。
  • 总之: 在允许的情况下,尽量依次填充,但是需要保证(32位系统)
  • 1 char,bool只从X地址处开始存储;
  • 2 short只从2X地址出开始存储;
  • 3 int,float,long只从4X地址处开始存储;
  • 4double只从8X地址处开始存储;

下面是列子:

#include <iostream>
using namespace std;

//sizeof(union1) = 16
union union1 {
	long i;		//4
	int x[4];	//16
	char ch;	//1
};

//sizeof(union2) = 16
union union2{
	char a[13];
	int i;	//由于int的存在,使得union按照四个字节来对其了
};

//sizeof(union3) = 13
union union3{
	char a[13];
	char i;
};

/////////////// 对比node1和node2 ///////////
struct node1{	//24
	int j;		//4
	double f;	//8	
	int i;		//4
};
	
struct node2{	//16
	int i;		//4
	int j;		//4
	double f;	//8	
};

/////////////// 对比node3和node4 ///////////
struct node3{	//32(注意)
	char i;		//1
	int d[5];	//20
	double f;	//8	
};

struct node4{	//40
	int d[5];	//20
	double f;	//8	
	int i;		//4
};

///////////////////////////////////////////
struct node5{	//32(注意)
	char d[10];	//10
	double f;	//8	
	int i;		//4
};

struct node6{	//20
	char d;		//1
	int f;		//4
	char i[10];	//10
};
//}__attribute__((aligned (1)));
///////////////////////////////////////
struct node7{	//12
	char x1;	//1
	short x2;	//2
	float x3;	//4
	char x4;	//4
};

#pragma pack(1) //指定按照1字节对齐
struct node8{	//8
	char x1;	//1
	short x2;	//2
	float x3;	//4
	char x4;	//1
};
#pragma pack()	//恢复缺省的字节对齐设置
////////////////////////////////////////
struct node9{	//20
	char ch,*p;	//1,4
	union{		//4
		short a,b;	
		unsigned int c:2,d:1;
	}u;
	bool f;		//1
	struct node9 *next;	//4
};

//测试字节对齐
void test2(){
	int size;
	struct node1 n1;
	struct node2 n2;
	struct node3 n3;
	struct node4 n4;
	struct node5 n5;
	struct node6 n6;
	struct node7 n7;
	struct node8 n8;
	struct node9 n9;
	//栈生长的方向与地址增长方向相反,所以a的地址比b的地址大四字节
	int a = 1,b = 2,c=3;
	int *p = &b;
	printf("%d\n",*(p+1));	//1
	
	//测试union和struct的大小(后者会地址对齐,前者仍然输出16)
	printf("union1:%d\n",sizeof(union union1));	//16
	printf("union2:%d\n",sizeof(union union2));	//16
	printf("union3:%d\n",sizeof(union union3));	//13

	//测试结构体的地址对齐
	printf("************************\n");
	printf("n1:%d\n",sizeof(n1));			
	printf("%ld\n",(unsigned long)&n1.j);	
	printf("%ld\n",(unsigned long)&n1.f);
	printf("%ld\n",(unsigned long)&n1.i);

	printf("************************\n");
	printf("n2:%d\n",sizeof(n2));		
	printf("%ld\n",(unsigned long)&n2.i);
	printf("%ld\n",(unsigned long)&n2.j);
	printf("%ld\n",(unsigned long)&n2.f);

	printf("************************\n");
	printf("n3:%d\n",sizeof(n3));		
	printf("%ld\n",(unsigned long)&n3.i);
	printf("%ld\n",(unsigned long)&n3.d);
	printf("%ld\n",(unsigned long)&n3.f);

	printf("************************\n");
	printf("n4:%d\n",sizeof(n4));		
	printf("%ld\n",(unsigned long)&n4.d);
	printf("%ld\n",(unsigned long)&n4.f);
	printf("%ld\n",(unsigned long)&n4.i);

	printf("************************\n");
	printf("n5:%d\n",sizeof(n5));		
	printf("%ld\n",(unsigned long)&n5.d);
	printf("%ld\n",(unsigned long)&n5.f);
	printf("%ld\n",(unsigned long)&n5.i);

	printf("************************\n");
	printf("n6:%d\n",sizeof(n6));		
	printf("%ld\n",(unsigned long)&n6.d);
	printf("%ld\n",(unsigned long)&n6.f);
	printf("%ld\n",(unsigned long)&n6.i);

	printf("************************\n");
	printf("n7:%d\n",sizeof(n7));		
	printf("%ld\n",(unsigned long)&n7.x1);
	printf("%ld\n",(unsigned long)&n7.x2);
	printf("%ld\n",(unsigned long)&n7.x3);
	printf("%ld\n",(unsigned long)&n7.x4);

	printf("************************\n");
	printf("n8:%d\n",sizeof(n8));
	printf("%ld\n",(unsigned long)&n8.x1);
	printf("%ld\n",(unsigned long)&n8.x2);
	printf("%ld\n",(unsigned long)&n8.x3);
	printf("%ld\n",(unsigned long)&n8.x4);

	printf("************************\n");
	printf("n9:%d\n",sizeof(n9));
	
}

int main(){
	int *ptr;
	test2();
	printf("************************\n");
	printf("char:%d\n",sizeof(char));		//1
	printf("short:%d\n",sizeof(short));		//2
	printf("int:%d\n",sizeof(int));			//4
	printf("long:%d\n",sizeof(long));		//4
	printf("float:%d\n",sizeof(float));		//4
	printf("double:%d\n",sizeof(double));	//8
	printf("pointer:%d\n",sizeof(ptr));		//4
	return 0;
}


分享到:
评论

相关推荐

    一种快速清空结构体的方法

    // 将结构体的起始地址进行强制转型,传入起始地址,用sizeof函数求出结构体的大小。} 这个算法比较简单,也没什么含量。但是希望大家有什么好的算法,也分享出来给大家,大家一起学习进步。

    详解C++ sizeof(下)

    sizeof作用于基本数据类型,在特定的平台和特定的编译器中,结果是确定的,如果使用sizeof计算构造类型:结构体、联合体和类的大小时,情况稍微复杂一些。 1.sizeof计算结构体 考察如下代码: struct S1 { char c; ...

    C/C++结构体字节对齐详解

     sizeof(s1)在VC6中按默认设置得到的结果为8。  我们先看看sizeof的定义——sizeof的结果等于对象或者类型所占的内存字节数,好吧,那让我们来看看S1的内存分配情况  S1 s1 = { 'a', 0xFFFFFFFF };  定义...

    浅析C++中结构体的定义、初始化和引用

    定义:结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。 声明一个结构体类型的形式是: 代码如下:struct Student{ //声明一个结构体类型Student int num; //声明一个整形变量num ...

    c++里初始化结构体的一个比较的简单方法

    //常用方法 struct MYSTRUCT ...{ int i,j,q; char szName[15]; MYSTRUCT() ...{ i = j = q = 0; memset(szName,0,sizeof(szName)); } }; //我想的方法 一个初始化结构体比较省事的方法

    C++结构体里面string类型赋值问题

    q=(struct temp*)malloc(sizeof(struct temp)); q-&gt;s=p; }  上述那种情况的赋值会导致程序中断  需要用用new来分配内存,malloc不会调用结构函数  结构体内的string不定长,不能动态分配内存。 #include ...

    sizeof详细总结

    1、定义与语法 2、语法形式 3、基本数据类型的sizeof值 4、指针变量的sizeof值 5、数组的sizeof值 6、结构体的sizeof值(★★★★★) 7、含位域结构体的sizeof

    C/C++语言中结构体的内存分配小例子

    当使用了 #pragma 指令指定编译器的对齐位数时,结构体按最长宽度的数据成员的宽度和 #pragma 指令指定的位数中的较小值对齐。 #pragma 指令格式如下所示:#pragma pack(4) // 或者 #pragma pack(push, 4) 举例如下...

    C++ sizeof 使用规则及陷阱分析

    计算结构体大小可以采用元素摆放法,我举例子说明一下:首先,CPU判断结构体的对界,根据上一节的结论,s1和s2的对界都取最大的元素类型,也就是double类型的对界8。然后开始摆放每个元素。 对于s1,首先把a放到8的...

    C/C++结构体对齐规则

     那么经过sizeof后得出结果是 12, 因为默认内存占用4byte, 变量a占用1byte,剩下3个,不足以存放变量b,故变量a也占用了4byte, 变量c由于后面没有了数据, 也会变为4byte,后sizeof值为12。 #include "stdafx....

    字节对齐与结构体大小

    结构体的sizeof值,并不是简单的将其中各元素所占字节相加,而是要考虑到存储空间的字节对齐问题。

    C++中类的内存空间大小(sizeof)分析

    在C语言中存在关于结构体的存储空间大小是比较深入的话题,其中涉及计算机的基本原理、操作系统等。我认为对齐是C语言中让很多初学者都拿不准摸不透的问题,特别是在跨平台的情况下,对齐这种问题更加的复杂多变,每...

    C++基础编程 学习笔记

    C++基础编程,适合小白和跨专业的同学学习,涉及 C++介绍(注释,变量,关键字,标识符命名规则)...结构体(结构体定义和使用,结构体数组,结构体指针,结构体嵌套结构体,结构体做函数参数,结构体中const使用场景)

    深入剖析C++中的struct结构体字节对齐

    现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间...

    经典c/c++笔试面试题汇总

    多年收集的c、c++经典书籍汇总 华为笔试面试题面试宝典 嵌入式 深入理解指针

    c++面试题基础分享.doc

    22.C++中vector和list的区别 23.结构体和类的区别 24.STL中map和set的原理(关联式容器) 25.MFC的消息机制 26.消息映射 27.列举几种进程的同步机制,并比较其优缺点 28.数组和链表的区别 29.MFC主要要用到哪...

    C/C++程序员面试指南.杨国祥(带详细书签).pdf

    本书以流行的面试题讲解为主要内容,介绍了C、C++语言基本概念,包括保留字、字符串、指针和引用、结构体、库函数等各个方面的基础知识,介绍了面向对象编程基本概念,包括如何实现继承、多态和封装等。还介绍了排序...

    计算机语言中c/c++的基础入门学习代码记录(适应于计算机二级)

    8.指针(01sizeof运算符;02指针的定义和使用;03指针间接接触赋值;04指针作为函数参数;05数组名作为函数参数;06函数返回值为指针类型;07数组和指针;08指针数组;09多级指针) 9.结构体(01typedef语句;02...

    C++开发工程师面试题库.docx

    * 在大部分 C++ 的实现中,带有虚函数的类的前 4 个字节是虚函数表的入口地址。 结构体和字节对齐 * 在 32 位 Windows 系统或 Linux 系统下,结构体 `A`、`B` 和 `C` 的大小分别是 3、6 和 7 字节。 * C 语法的...

    C++ 小型复数计算器

    struct User //用户结构体类型定义 { char szName[20]; //用户名 int nTime; //使用次数 int nTest; //测试次数 double alAve; //平均成绩 int nAdd; //加法次数 int nSub; //减法次数 int nMul; //乘法次数 double ...

Global site tag (gtag.js) - Google Analytics