struct、union、enum and sizeof

struct 

1、结构体和数组的区别:可以再结构体里声明数组;结构体变量可以相互赋值,而数组不行。

2、struct与class的区别:class的成员访问权限默认是private,而struct成员的是public。

3、结构体的定义:

(1)可递归。结构体内部可以使用指针指向自己。例如,链表。

(2)可嵌套。结构体内部可以包含其他的结构体。

4、结构体中的位域。

在存储信息时,不需要占用一个完整的字节,而只需要占几个或一个二进制位。

          位域定义与结构定义相仿,其形式为:

struct 位域结构名

 类型说明符 位域名:位域长度

 };

例如:

struct bs
{
int a:8;
int b:2;
int c:6;
}data;

         分析:data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。


对于位域的定义尚有以下几点说明: 

        1. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。

        2. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。

        例如:

struct bs

{

unsigned a:4

unsigned :0 /*空域*/

unsigned b:4 /*从下一单元开始存放*/

unsigned c:4

}

在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。


union

         结构体和共用体都是由多个不同类型的数据类型成员组成,但是在任一时刻,共用体中只存放了一个被选中的成员。而结构体

所有成员都纯在。对于共用体的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了。

(1)结构体占用内存,可能超过各个成员内存量的和,而共用体占用的内存为各个成员中占用最大者内存。

(2)union和struct在内存中的存放顺序是从地地址开始存放的。

               大端存储:数据的高字节存放在低地址中。小端存储:数据的低字节存放在低地址中。


enum

(1)定义

        enum   枚举类型名
  {
                 枚举表
  }


例如:

     enum ColorEnum1
  {

  红色, //注意,系统会默认给它赋值为0

  蓝色, //系统赋值为1

  黑色, //系统赋值为2

  粉红色 //系统赋值为3

  }


     enum ColorEnum2
  {

  红色=1, //用户自己赋值 所以枚举是一组 符号名称/值 配对

  蓝色, // 系统赋值为2

  黑色=1, //用户自己赋值1

  粉红色 //系统赋值为2

  }
         

              所以可以看出,系统会自己给没有赋值的常量赋值,但赋值的方式是按照上一个的值+1来进行操作的


sizeof(struct/union/enum)

一般32位机子上各个数据类型所占的存储空间如下:

char:8位

short:16位

int:32位

long:32位

float:32位

double:64位


一、struct,结构体。

        请牢记以下3条原则:(在没有#pragma pack宏的情况下)

1、数据成员对齐规则:结构体(struct)的数据成员,第一个数据成员放在offset为0的地方,之后的每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int在32位机子上为4字节,所以要从4的整数倍地址开始存储)。


2、结构体作为成员:如果一个结构体里同时包含结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储

(如struct a里有struct b,b里有char,int ,double等元素,那么b应该从8(即double类型的大小)的整数倍开始存储)。


3、结构体的总大小:即sizeof的结果。在按对齐原则计算出来的大小的基础上,必须还得是其内部最大成员的整数倍.

不足的要补齐(如struct里最大为double,现在计算得到的已经是11,则总大小为16)。

例子:

typedef struct bb
{
	int id;             //[0]....[3]      表示4字节
	double weight;      //[8].....[15]      原则1
	float height;      //[16]..[19],总长要为8的整数倍,仅对齐之后总长为[0]~[19]为20,补齐[20]...[23]     原则3
}BB;
typedef struct aa  
{  	
	int  id;         //[0]...[3]          原则1  
	double score;     //[8]....[15]      
	short grade;    //[16],[17]          
	BB b;             //[24]......[47]       原则2(因为BB内部最大成员为double,即8的整数倍开始存储)  
	char name[2]; //[48][49]
}AA; 
int main()
{
	cout<<sizeof(AA)<<" "<<sizeof(BB)<<endl;
	return 0;
}
输出结果为56 24

         

         编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式。//n为1、2、4、8、16...

         1、n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默 认的对齐方式,即该变量所占用字节数的整数倍;第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。

         2、结构体的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。

         所以在上面的代码前加一句#pragma pack(1),则代码输出为

         bb:(0~3)+(4~11)+(12~15)=16;

         aa:(0~1)+(2~5)+(6~13)+(14~15)+(16~31)=32,也就是说,#pragma pack(1)就是没有对齐规则。

         再考虑#pragma pack(4),

          bb:(0~3)+(4~11)+(12~15)=16;

          aa:(0~1)+(4~7)+(8~15)+(16~17)+(20~35)=36

     

二、union共用体(联合)

        在union中,所有的共用体成员共用一个空间,并且同一时间只能储存其中一个成员变量的值其长度为联合体中元类型最大的变量长度的整数倍。并且要考虑其他成员变量的对齐

union foo
{
char s[10];
int i;
}
   sizeof(foo) 的内存空间的长度为12,而并不是数组的长度10。考虑对齐,必须要是4(int的大小)的整数倍。

   若把int改为double,则foo的内存空间为16,是double型的两倍。

union   mm{  
  char   a;//元长度1        1
  int   b[5];//元长度4     20
  double   c;//元长度8     8
  int   d[3];              12
  };  

考虑到8和12的对齐, 所以sizeof(mm)=24。


三、enum

  enum只是定义了一个常量集合,里面没有元素,把它当做int型存储,所以sizeof的大小为4 byte。


【大小端】

判断大小端的方法:1、利用指针,2、利用union。


#include <stdlib.h>
#include <stdio.h>

int main()
{
	int x = 0x10000001;
	char *p = (char *)&x;

	if (*p)
	{
		printf("little\n");
		printf("%d\n", *p);
	}
	else
	{
		printf("large\n");
	}

	system("pause");
	return 0;
}

#include "stdio.h"
#include<stdlib.h>

int main()
{
	union w
	{
		int a;  //4 bytes
		char b; //1 byte
	} c;
	c.a = 1;
	if (c.b == 1)
		printf("It is Little_endian!\n");
	else
		printf("It is Big_endian!\n");

	system("pause");
	return 1;
}

下面这段代码输出也耐人寻味。

#include<stdio.h>
#include<stdlib.h>

union {
	char i[4];
	short x;
}s;

int main()
{
	s.x = 0;
	s.i[0] = 256;
	s.i[1] = 255;
	s.i[2] = 254;
	s.i[3] = 253;
	
	printf("s.x is %d \n", s.x);
	printf("s.i[0] is %d \n", s.i[0]);
	printf("s.i[1] is %d \n", s.i[1]);
	printf("s.i[2] is %d \n", s.i[2]);
	printf("s.i[3] is %d \n", s.i[3]);
	system("pause");
}






你可能感兴趣的:(enum,UNION,struct)