struct、union、enum and sizeof

原创 2015年07月11日 11:02:23

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");
}






版权声明:如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!本文为博主原创文章,转载请注明链接!

相关文章推荐

结构体struct、枚举enum、联合体union、位字段、自定义类型typedef、字节对齐

结构体struct 1 结构体的基本知识 2 结构体与函数 3 结构体数组 4 自引用结构体 枚举变量enum 联合体union 位字段 1 一般的方法定义屏蔽吗 2 用位字段来定义屏蔽吗 自定义类型...

结构struct 联合Union和枚举Enum的细节讨论

联合(Union)是一种构造数据类型,它提供了一种使不同类型数据类型成员之间共享存储空间的方法,同时可以实现不同类型数据成员之间的自动类型转换。联合体对象在同一时间只能存储一个成员的值。联合的内存大小...
  • is2120
  • is2120
  • 2011年03月15日 17:45
  • 1340

关于struct,union,enum三大复合数据类型

struct结构体 struct声明一个结构体,它将一些相关联的数据打包成一个整体。 首先看结构体占用内存空间的大小。 struct student {   }stu; sizeof(s...

结构体(struct)、联合体(union)、枚举(enum) 三种结构的区别及各个结构细节的总结

今天上网无意中看到了union结构, 好久不用了, 回想了一下结构体(struct)、联合体(union)、枚举(enum)各自的特点及用法,并在网上查了些资料,总结在这里,以备以后查看. C和C...

c学习的基本问题-4:关于struct,union,enum

struct的定义:struct  结构标签{      类型1 标识符1;      类型2 标识符2;      类型3 标识符3;      类型4 标识符4;      类型5 标识符5;};...
  • zmmmap
  • zmmmap
  • 2011年04月27日 16:01
  • 380

struct union enum

1 struct #include #include #define SIZE 10 struct list{ int value[10]; struct list *next; }; ...

补遗篇之struct(enum/union)多种定义方式

结构体(struct)是各种变量组合形成的新数据类型,struct有多种定义形式,总结下来可分四种,初学者容易混淆。下面一并整理区分,其中要特别留意区分三个元素:结构标签名,结构变量名,结构别名。 ...
  • ipmux
  • ipmux
  • 2013年12月14日 11:51
  • 720

C语言中的struct、union、enum、Typedef

一、typedef的用法 转载地址: http://www.2cto.com/kf/201404/296683.html typedef可以看...

C_C语言的enum、struct、union的使用详解

OK今天我们讲解C语言的三个特殊

Struct和Union的sizeof计算

struct 结构体的大小不是简单的成员相加,要考虑存储空间的字节对齐 1、空结构体的大小为1 2、含有static的结构体在计算大小时不算上static变量,因为static存储在全局数据空间...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:struct、union、enum and sizeof
举报原因:
原因补充:

(最多只允许输入30个字)