`
jiq408694711
  • 浏览: 36596 次
  • 性别: 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/C++中结构体(struct)知识点强化

    ### C/C++中结构体(struct)知识点强化 #### 结构体定义与理解 在C/C++编程语言中,**结构体(struct)**是一种用户自定义的数据类型,它允许开发者将不同类型的变量组合在一起形成一个单一的实体。这为解决复杂问题...

    C/C++ 结构体与共用体教程

    结构体与共用体是 C 和 C++ 语言中非常重要的数据类型,它们允许我们将多个不同类型的数据组合成一个复合类型,方便管理和操作。本教程将详细讲解这两个概念,包括定义、使用和相关的高级特性。 11.1 定义一个结构...

    C#调用C++DLL传递结构体数组的终极解决方案

    在C#和C++混合编程中,常常需要跨语言调用DLL中的函数,而结构体数组是常见的数据传输对象。由于C#和C++对内存管理的方式不同,直接传递结构体数组可能会遇到问题。本文将详细介绍如何解决这个问题,确保C#成功调用...

    C#中调用C++中动态链接库DLL中的结构体

    C++允许直接操作内存,而C#则通过垃圾回收机制自动管理内存,这在处理结构体时尤其重要,因为C++结构体的布局可能与C#类的布局不同。因此,当C#与C++交互时,需要确保数据类型和内存对齐方式的一致性。 1. **定义互...

    c++结构体string无法用malloc分配内存

    标题中提到的问题是关于“c++结构体string无法用malloc分配内存”。这是因为`malloc()`函数仅分配指定大小的内存空间,但不会调用任何构造函数。对于非POD(Plain Old Data)类型的成员,如`std::string`,它需要...

    C#与C++通讯字节流转换结构体

    在C++的头文件定义中,使用了`#pragma pack 1`字节对齐,所以C#的结构体也必须要加上对应的特性,`LayoutKind.Sequential`属性让结构体在导出到非托管内存时按出现的顺序依次布局,而对于C++的char数组类型,C#中...

    c++ socket 编程

    以上就是C++中使用Socket进行结构体消息传递的基本步骤。在实际项目中,可能还需要处理异常、添加超时机制、优化性能等问题。`SocketTest`和`SocketClientTest`这两个文件可能是示例代码,你可以参考它们来更好地...

    C#结构体和C++字节数组的转换

    在跨语言通信或数据交换中,尤其是在涉及到C#与C++之间进行TCP通信时,由于两者数据表示方式的差异,可能会遇到将C#中的结构体转换为C++可理解的字节数组,或者反过来的过程。本文将详细介绍如何在C#中实现结构体与...

    c++中关于结构体长度的计算问题.pdf

    "C++结构体长度计算问题" 一、结构体长度计算的重要性 在C++编程中,结构体的长度计算是一个非常重要的问题。很多开发者都知道,结构体的sizeof值,不是简单的将其中各元素所占字节相加,而是要考虑到存储空间的...

    C#向C++封送结构体数组[归类].pdf

    这里使用`LayoutKind.Sequential`布局,确保C#结构体与C++结构体的内存布局一致。`MarshalAs`属性用于指定如何封送字段,例如`UnmanagedType.ByValTStr`用于字符串,`UnmanagedType.ByValArray`用于数组。 然而,...

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

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

    sizeof 数据结构 C++/C 面试题

    在C++和C编程语言中,`sizeof`运算符是一个非常重要的知识点,它用于计算一个类型或变量在内存中占用的字节数。这个运算符对于理解和优化代码,特别是涉及数据结构和内存管理的部分,至关重要。下面我们将深入探讨`...

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

    在C++编程中,初始化结构体是一个常见的任务,它确保结构体的所有成员变量都被赋予了合适的初始值。这里我们探讨两种不同的初始化结构体的方法,并分析它们的优缺点。 首先,让我们看看传统的方法,也就是在结构体...

    C++与倍福PLC写结构体类型数据

    要将这个结构体数据写入倍福PLC,首先需要在TwinCAT项目中定义相应的变量结构,并确保其与C++结构体相对应。接着,引入Ads倍福dll库并使用提供的API函数,如`AdsAddDevice`、`AdsAddReadDeviceVariable`、`...

    sizeof 用法汇总 C和C++的语法

    `sizeof`是C和C++中的一个非常重要的运算符,用于获取任何数据类型或变量在内存中占用的字节数。下面将详细讲解`sizeof`的用法。 1. `sizeof`与`strlen`的区别: - `strlen()`函数主要用于计算字符数组(字符串)...

    向文件写结构体,或从文件读取结构体 VC

    如果结构体中包含C++特有的类型(如指针或动态分配的数组),那么直接读写可能会出现问题,因为它们在内存中可能不是连续的。此时,需要自定义序列化和反序列化逻辑。 在实际开发中,除了基本的结构体,我们还可能...

Global site tag (gtag.js) - Google Analytics