C++基础—结构体(struct)

转自:http://blog.csdn.net/cainv89/article/details/48447225

1. 结构体(struct)

1.1 结构体的定义

  • 结构体(struct):举凡出于同密密麻麻有相同类别或者不同类型的数量做的数量集合,叫做结构。
  • 结构体(struct):举凡一致种复合数据类型,结构类型。
  • 横流:“结构”是千篇一律种植构造类型,它是由几“成员”组成的。
    每一个成员可以是一个中心数据列或者又是一个构造类型。
    结构即是同样栽“构造”而变成的数据类型,
    那么当说明与下之前要优先定义其,也就是结构其。如同在认证与调用函数之前若优先定义一样。

1.2 C语言中之结构体

  • 说明:每当C语言中,结构体(struct)是复合数据类型的均等种。同时为是部分因素的汇,这些因素称为结构体的成员,且这些成员可以为歧之类型,成员一般用名字访问。结构体可以吃声称也变量、指针或数组等,用以实现比复杂的数据结构。
  • 流动:在C语言中,结构体不可知包含函数。
  • 概念和声明: (1)示例代码一:

    1 struct tag 
    2 {
    3     member-list
    4 }variable-list;
    5 注:struct为结构体关键字;
    6    tag为结构体的标志;
    7    member-list为结构体成员变量列表,其必须列出其所有成员;
    8    variable-list为此结构体声明的变量;
    

    (2)示例代码二:

     1 //此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c,但没有标明其标签,声明了结构体变量s1
     2 struct 
     3 {
     4     int a;
     5     char b;
     6     double c;
     7 } s1;
     8 
     9 //此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c,结构体的标签被命名为SIMPLE,用SIMPLE标签的结构体,另外声明了变量t1, t2[20], *t3
    10 struct SIMPLE
    11 {
    12     int a;
    13     char b;
    14     double c;
    15 };
    16 SIMPLE t1, t2[20], *t3; 
    17 
    18 //可以用typedef创建新类型,此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c,结构体的标签被命名为Simple2,用Simple2作为类型声明新的结构体变量u1, u2[20], *u3
    19 typedef struct
    20 {
    21     int a;
    22     char b;
    23     double c; 
    24 } Simple2;
    25 Simple2 u1, u2[20], *u3;//若去掉typedef则编译报错,error C2371: “Simple2”: 重定义;不同的基类型
    26 
    27 注:在上面的声明中,第一个和第二声明被编译器当作两个完全不同的类型,即使他们的成员列表是一样的,如果令t3=&s1,则是非法的。
    

    流淌:在形似情形下,tag、member-list、variable-list这3组成部分足足要出新2单。

1.3 C++中的结构体

  • 说明:以C语言中,结构体不能够包含函数。在面向对象的程序设计受到,对象具备状态(属性)和作为,状态保存在成员变量中,行为经过分子方法(函数)来落实。C语言中的结构体只能描述一个目标的状态,不克描述一个靶的行事。在C++中,考虑到C语言到C++语言过渡的连续性,对结构体进行了扩大,C++的结构体可以涵盖函数,这样,C++的结构体也颇具类似的意义,与class不同的是,结构体包含的函数默认为public,而无是private。
  • 流淌:在C++中,结构体可以分包函数。
  • 概念及声明:

  • (1)示例代码一:

    1 struct tag 
    2 {
    3     member-list
    4 }variable-list;
    5 注:struct为结构体关键字;
    6    tag为结构体的标志;
    7    member-list为结构体成员变量及成员函数列表,其必须列出其所有成员;
    8    variable-list为此结构体声明的变量;
    

    (2)示例代码二:

     1 #include <iostream> 
     2 
     3 using namespace std;
     4 
     5 struct SAMPLE
     6 {
     7     int x;
     8     int y;
     9     int add() {return x+y;}
    10 }s1;
    11 
    12 int main()
    13 {
    14     cout<<"没初始化成员变量的情况下:"<<s1.add()<<endl;
    15     s1.x = 3;
    16     s1.y = 4;
    17     cout<<"初始化成员变量的情况下:"<<s1.add()<<endl;
    18     system("pause");
    19     return 0;
    20 }
    21 =>没初始化成员变量的情况下:0
    22   初始化成员变量的情况下:7
    

    C++中的结构体与类似的分:
    (1)class中默认的积极分子访问权限是private的,而struct中则是public的。
    (2)class继承默认是private继承,而从struct继承默认是public继承。

1.4 结构体的图

  • 以实际项目被,结构体是大量留存的。研发人员每每下结构体来封装一些特性来做新的种类。由于C语言内部程序比较简单,研发人员日常以结构体创造新的“属性”,其目的是简化运算。
  • 结构体在函数中的企图不是方便,最好根本的意向就是是包裹。装进的补就是可以重新使用。让使用者不必关心这是呀,只要根据定义使用就好了。

1.5 结构体的高低和内存对一起

  • 默认的针对齐方式:诸成员变量在寄放的时候因当布局面临起的相继依次申请空间,同时依照上面的针对性齐方式调整岗位,空缺的字节VC会自动填写。同时VC为了保布局的大大小小也结构的字节边界数(即该组织面临占据最老空间的型所占的字节数)的翻番,所以于也尾声一个成员变量申请空间后,还见面依据需要活动填写充空缺的字节。

  • 流淌:VC对变量存储的一个异处理。为了增进CPU的囤速度,VC对有些变量的开局地址做了“对共同”处理。在默认情况下,VC规定各级成员变量存放的开始地址相对于结构的起始地址之偏移量必须也该变量的种类所占的字节数之翻番。

  • (1)示例代码一:

    1 struct MyStruct
    2 {
    3     double dda1;
    4     char dda;
    5     int type;
    6 };
    7 //错:sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13。
    8 //对:当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为16。
    

    流淌:为面的组织分配空间的下,VC根据成员变量出现的逐条与针对齐方式。

  • (1)先乎率先个分子dda1分配空间,其开头地址及结构的开局地址一样(刚好偏移量0刚好也sizeof(double)的倍数),该成员变量占用sizeof(double)=8个字节;

  • (2)接下也次个分子dda分配空间,这时下一个好分配的地方对于组织的序曲地址的偏移量为8,是sizeof(char)的翻番,所以将dda存放于偏移量为8底地方满足对齐方式,该成员变量占用sizeof(char)=1独字节;

  • (3)接下也老三个成员type分配空间,这时下一个得以分配的地方对于组织的苗子地址的偏移量为9,不是sizeof(int)=4的倍数,为了满足对齐方式对偏移量的律问题,VC自动填充3独字节(这三个字节没有放开什么东西),这时下一个可以分配的地址对于组织的原初地址的偏移量为12,刚好是sizeof(int)=4的翻番,所以把type存放于偏移量为12之地方,该成员变量占用sizeof(int)=4独字节;
  • 这时整个结构的积极分子变量已经还分配了空中,总的占有的空中大小也:8+1+3+4=16,刚好也结构的字节边界数(即组织中占有最深空间的档次所占据的字节数sizeof(double)=8)的倍数,所以无空缺的字节需要填写。所以全结构的高低为:sizeof(MyStruct)=8+1+3+4=16,其中起3独字节是VC自动填充的,没有放开任何发生意义的事物。

  • (2)示例代码二:交换一下上述例子中MyStruct的成员变量的职位

  • 1 struct MyStruct

    2 {
    3     char dda;
    4     double dda1;
    5     int type;
    6 };
    7 //错:sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13。
    8 //对:当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为24。
    

     

  • 流淌:为面的组织分配空间的时刻,VC根据成员变量出现的逐条及针对齐方式。

  • (1)先乎率先个分子dda分配空间,其开场地址和结构的起始地址一样(刚好偏移量0刚好也sizeof(char)的倍数),该成员变量占用sizeof(char)=1个字节;

  • (2)接下吗第二单成员dda1分红空间,这时下一个可分配的地址对于组织的开局地址之偏移量为1,不是sizeof(double)=8的翻番,需要补充足7只字节才能够而偏移量变为8(满足对齐方式),因此VC自动填充7个字节,dda1存放在偏移量为8之地址上,它占用8只字节;

  • (3)接下呢老三只分子type分配空间,这时下一个足以分配的地方对于组织的胚胎地址的偏移量为16,是sizeof(int)=4的翻番,满足int的指向齐方式,所以未欲VC自动填充,type存放于偏移量为16之地址上,该成员变量占用sizeof(int)=4独字节;
    此刻整个结构的成员变量已经还分配了空间,总的占有的空间尺寸为:1+7+8+4=20,不是布局的节边界数(即组织中占有最要命空间的类型所占据的字节数sizeof(double)=8)的倍数,所以用填写4个字节,以满足结构的分寸为sizeof(double)=8的翻番。所以该组织总的深浅为:sizeof(MyStruct)为1+7+8+4+4=24。其中到底的发生7+4=11单字节是VC自动填充的,没有放开其他发生含义的东西。

  • 字节的指向齐方式:

  • 在VC中提供了#pragmapack(n)来设定变量以n字节对齐方式。n字节本着齐就是说变量存放的起始地址的偏移量有少数种情景:第一,如果n大于等于该变量所占的字节数,那么偏移量必须满足默认的对齐方式;第二,如果n小于该变量的种类所占用的字节数,那么偏移量为n的翻番,不用满足默认的针对性齐方式。结构的总大小为产生只约束原则,分下面两种状况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小要为占用空间不过老之变量占用的空间数的倍数;否则要为n的翻番。


注:VC对结构的存储的特殊处理确实提高了CPU存储变量的速度,但有时也会带来一些麻烦,我们也可以屏蔽掉变量默认的对齐方式,自己来设定变量的对齐方式。**
  • (1)示例代码:

     1 #pragmapack(push)//保存对齐状态
     2 
     3 
     4 #pragmapack(4)//设定为4字节对齐
     5 
     6 struct test
     7 {
     8     char m1;
     9     double m4;
    10     int m3;
    11 };
    12 
    13 #pragmapack(pop)//恢复对齐状态
    

     

    流淌:以上结构的大小也16,下面分析其储存情况。

  • (1)首先为m1分配空间,其偏移量为0,满足我们和好设定的指向齐方式(4字节针对联合),m1占用1个字节;

  • (2)接着开吧m4分配空间,这时该偏移量为1,需要补足3单字节,这样如果偏移量满足吗n=4的翻番(因为sizeof(double)大于n),m4占用8独字节;

  • (3)接着为m3分配空间,这时该偏移量为12,满足吗4底倍数,m3占用4个字节;
    这时已为持有成员变量分配了空间,共分配了16只字节,满足为n的倍数。如果拿点的#pragmapack(4)改为#pragma
    pack(8),那么我们好博结构的大小也24。

参考文献: 

[1]《C++全方位学习》范磊——第六回 

[2]《C++程序设计教程(第二本子)》钱会——第八段  [3]

 百度搜索关键字:结构体、结构体的图、结构体的高低和内存对一头