文档章节

C语言中struct, union, enum 三大复合数据类型

henry-zhang
 henry-zhang
发布于 2015/04/15 16:41
字数 1850
阅读 85
收藏 0

struct结构体

struct声明一个结构体,它将一些相关联的数据打包成一个整体。

首先看结构体占用内存空间的大小。

struct student

{

 

}stu;

sizeof(stu)是多少?

这里我们联想到前面讲到的模子的概念,大概就知道答案了。

关于求结构体所占内存空间的大小,我们遵循字节对齐的原则,计算的出的结果是8的倍数。看下面的代码:

struct student

{

    char i;

    int x;

    float c;

    double a;

}stu;

结果是24。分析为什么?

一个很少用的概念:柔性数组。在计算结构体大小时,并不计算在内,他和结构体没有任何联系。

struct student

{

    char i;

    int x;

    float c;

    double a;

    int m[];

}

结果是多少?为什么?

运算符sizeof可以计算出给定类型的大小,对于32位系统来说,sizeof(char) = 1; sizeof(int) = 4。基本数据类型的大小很好计算,我们来看一下如何计算构造数据类型的大小。
C语言中的构造数据类型有三种:数组、结构体和共用体。
数组是相同类型的元素的集合,只要会计算单个元素的大小,整个数组所占空间等于基础元素大小乘上元素的个数。
结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。看下面这样的一个结构体:
struct stu1
          {
                int i;
                char c;
                int j;
          };
先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成
员的偏移量加上最后一个成员的大
小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,第一个成员i的偏移量为0。第二个成员c的偏移量是第一个成员的偏移量加上第一个
成员的大小(0+4),其值为4;第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。
实际上,由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍) 二、结构体大小必须是所有成员大小的整数倍。
对照第一条,上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。
对照第二条,结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。
再看一个满足第一条,不满足第二条的情况
struct stu2
          {
                int k;
                short t;
          };
成员k的偏移量为0;成员t的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员k大小的整数倍。因此,编
译器会在成员t后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。
由此可见,大家在定义结构体类型时需要考虑到字节对齐的情况,不同的顺序会影响到结构体的大小。对比下面两种定义顺序
struct stu3
          { 
                char c1; 
                int i;
                char c2;
          }
struct stu4
          {
                char c1;
                char c2;
                int i;
          }
虽然结构体stu3和stu4中成员都一样,但sizeof(struct stu3)的值为12而sizeof(struct stu4)的值为8。
如果结构体中的成员又是另外一种结构体类型时应该怎么计算呢?只需把其展开即可。但有一点需要注意,展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。看下面的例子:
struct stu5
                {
                short i;
                struct 
                {
                   char c;
                   int j;
                } ss; 
                int k;
          }
结构体stu5的成员ss.c的偏移量应该是4,而不是2。整个结构体大小应该是16。
如何给结构体变量分配空间由编译器决定,以上情况针对的是Linux下的GCC。其他平台的C编译器可能会有不同的处理。


Union共用体

union维护足够的空间来放置多个数据成员中的一种,而不是每一个数据成员配置空间。在union中所有的数据成员共用一个空间,同一时间只能存储一个数据成员,所有的数据成员具有相同的起始地址。

union state

{

  char ch;

  int intmax;

  char *sh;

  double dou;

}st;

在上面的共用体中,union的内存空间就是double所占用的空间8.

那么,在计算机里面,数据的存储和系统的结构有关系,大端小段对数据存储又有什么关系?

大端模式:子数据的高字节存储在低地址,而子数据的低字节则存放在高地址中。

小端模式:子数据的高字节存储在高地址,而子数据的低字节则存放在低地址中。

union型数据所占据的空间等于最大的成员所占的空间。对union型的成员的存取都是相对于该联合体基地址的偏移量为0开始,也就是联合体的访问不论对哪个变量的存取都是从union的首地址位置开始。

既然这样,我们就可以通过union来判断当前系统的模式。

如果取出的低地址上的值为0,毫无疑问,这是大端模式,如果取出的是低地址上的值为1,就是小端模式。

  1. int checkState()

  2. {

  3.   union check

  4.   {

  5.     int i;

  6.     char ch;  

  7.   }c;

  8.   c.i = 1;

  9.   return (c.ch==1);

  10. }

     

程序代码如上所示。

 

enum枚举

一般的定义如下:

enum enum_type_name

{

    ENUM_CONST_1,

    ENUM_CONST_2,

     .....

    ENUM_CONST_B, 

}enum_variable_name;

enum_type_name 是自定义的一种数据类型名,而enum_variable_name 为enum_type_name 类型的一个变量,也就是枚举变量。实际上enum_type_name 类型是一个变量取值范围的限定,而花内是他的取值范围。括号里面的成员都是常量,也就是枚举常量。enum变量类型还可以给其中的常量符号赋值,如果不赋值就会从被赋值的那个常量开始一次家1,都没有赋值就从0开始一次加1.例如:

enum color

{

  GREEN = 1,

  RED,

  BLUE,

  GREEN_RED = 8,

  GREEN_BLUE

}colorVal;

则枚举常量的值为:

 GREEN = 1,

  RED = 2,

  BLUE = 3,

  GREEN_RED = 8,

  GREEN_BLUE = 9,

那么sizeof(colorVal)的大小是?答案是4.因为colorVal是一个枚举变量,而枚举变量代表的是一个整数


本文转载自:

henry-zhang
粉丝 2
博文 62
码字总数 1431
作品 0
海淀
私信 提问
C语言再学习--关键字

C语言一共有32个关键字,如下表所示: 关键字 说明 auto 声明自动变量 short 声明短整型变量或函数 int 声明整型变量或函数 long 声明长整型变量或函数 float 声明浮点型变量或函数 double 声...

qq_29350001
2016/11/03
0
0
itfriday/protocol-pack

Protocol-Pack简介 Protocol-Pack(以下简称PP)是和google的Protocol Buffer(简称PB)类似的一种二进制数据交换的格式。它采用TT(L)V(即Tag-Type-Length-Value)的格式对数据信息进行编码,具...

itfriday
2016/12/06
0
0
2675字带你进阶C语言中的关键字.md

C语言进阶之C语言关键字 关键字总结.png 基本数据类型 1.数据类型 数据类型可以理解为固定内存大小的别名(例如,在C语言中int数据类型代表了4个字节的内存) 数据类型是可以创建变量的模板...

PcDack
2017/12/03
0
0
C/C++/Python中类和类型的区别

类:class,类型:type (注意:python2.2 之后类与类型已经统一!!!) Class is a type. Types describe objects, references and functions. 所有的类型可以分为两大种: 1. 基本类型(int...

follitude
2015/12/16
159
0
3、C语言 —— 基本数据类型

一、C语言的数据类型 空类型(void) 指针类型(void *) 构造类型 数组 结构体(struct) 共用体(union) 枚举(enum) 基本数据类型 整型(int) 浮点型(单精度 float,双精度 double) ...

cobish
2014/06/13
134
0

没有更多内容

加载失败,请刷新页面

加载更多

CSS盒子模型

一、什么叫框模型 页面元素皆为框(盒子) 定义了元素框处理元素内容,内边距,外边距以及边框的计算方式 二、外边距 围绕在元素边框外的空白距离(元素与元素之间的距离) 语法:margin,定...

wytao1995
今天
4
0
Replugin借助“UI进程”来快速释放Dex

public static boolean preload(PluginInfo pi) { if (pi == null) { return false; } // 借助“UI进程”来快速释放Dex(见PluginFastInstallProviderProxy的说明) return PluginFastInsta......

Gemini-Lin
今天
4
0
Hibernate 5 的模块/包(modules/artifacts)

Hibernate 的功能被拆分成一系列的模块/包(modules/artifacts),其目的是为了对依赖进行独立(模块化)。 模块名称 说明 hibernate-core 这个是 Hibernate 的主要(main (core))模块。定义...

honeymoose
今天
4
0
精华帖

第一章 jQuery简介 jQuery是一个JavaScript库 jQuery具备简洁的语法和跨平台的兼容性 简化了JavaScript的操作。 在页面中引入jQuery jQuery是一个JavaScript脚本库,不需要特别的安装,只需要...

流川偑
今天
7
0
语音对话英语翻译在线翻译成中文哪个方法好用

想要进行将中文翻译成英文,或者将英文翻译成中文的操作,其实有一个非常简单的工具就能够帮助完成将语音进行翻译转换的软件。 在应用市场或者百度手机助手等各大应用渠道里面就能够找到一款...

401恶户
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部