关闭

struct、union、enum and sizeof

标签: structenumunion
728人阅读 评论(0) 收藏 举报
分类:

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






0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

《C关键字分析》之sizeof,enum、union和struct

一、关于sizeof 1.它是C的关键字,不是函数; 2.一般用法为sizeof 变量或sizeof(数据类型);后边这种写法会让人误认为是函数,但这种写法是为了防止和C中类型修饰符(static、c...
  • tankai19880619
  • tankai19880619
  • 2013-10-10 10:27
  • 1703

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

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

c语言之不再害怕sizeof(struct)

程序员在面试的时候经常会碰到一些题目,给出一个结构体,然后sizeof它一下,问值是多少?比如给出下面这样一个结构体: struct test{ char a; short ...
  • zzran
  • zzran
  • 2013-03-14 12:04
  • 8119

第六讲:c/c++复合数据类型struct以及联合类型union,动态内存申请malloc和calloc

关于复杂的变量类型——结构体的定义
  • xuan_zizizi
  • xuan_zizizi
  • 2017-04-08 15:47
  • 192

struct和 union用 sizeof 看字节对齐

转至   http://www.cnblogs.com/looksgood/archive/2009/10/29/1591949.html union u {  doub...
  • bore2015
  • bore2015
  • 2016-05-04 22:07
  • 284

结构体(Struct)联合体(Union)枚举(enum)总结

对于这三个结构型数据类型,也C/C++当中常见的数据类型。不过,结构体,联合体,枚举这三种数据类型都适合在何种情况下使用,恐怕大多数人都不胜了解,下面就从概念上一一区别和 研究。 结构体struct是...
  • qq_1223113455
  • qq_1223113455
  • 2016-05-30 08:58
  • 667

c语言中的结构(struct)和联合(union)简介

联 合(union)  1. 联合说明和联合变量定义  联合也是一种新的数据类型, 它是一种特殊形式的变量。  联合说明和联合变量定义与结构十分相似。其形式为:  union 联合名{  数...
  • xjbclz
  • xjbclz
  • 2016-07-04 22:22
  • 4145

枚举大小sizeof 中枚举的大小详解

至从C语言开始enum类型就被作为用户自定义分类有限集合常量的方法被引入到了语言当中,而且一度成为C++中定义编译期常量的唯一方法(后来在类中引入了静态整型常量)。 根据上面对enum类型的描述,有...
  • zzsfqiuyigui
  • zzsfqiuyigui
  • 2016-03-13 09:40
  • 4348

C语言之动态数组

/***************************************** **** Function 根据需要动态分配内存空间******** **********************...
  • lixiaogang_theanswer
  • lixiaogang_theanswer
  • 2017-04-21 18:10
  • 213

进程的用户栈和内核栈

进程是程序的一次执行过程。用剧本和演出来类比,程序相当于剧本,而进程则相当于剧本的一次演出,舞台、灯光则相当于进程的运行环境。进程的堆栈每个进程都有自己的堆栈,内核在创建一个新的进程时,在创建进程控制...
  • DLUTBruceZhang
  • DLUTBruceZhang
  • 2013-07-14 22:11
  • 3104
    个人资料
    • 访问:223120次
    • 积分:3722
    • 等级:
    • 排名:第10131名
    • 原创:131篇
    • 转载:1篇
    • 译文:0篇
    • 评论:59条
    博客专栏
    感谢打赏-支付宝二维码
    支付宝
    最新评论