总结结构体枚举联合位段

结构体

先简单的介绍一下结构体

结构体是一种类型,是一些值的集合,这些值称为成员变量。结构体的每个成员可以是不同类型的变量。

 

1. 结构体类型的创建

struct Stu

{

char name[4];

int age;

char sex;

}a*p;

这里Stu是结构体名称,a是结构体变量,*p是指向结构体的指针。在创建结构体时,结构体名称不能省略,否则无法引用结构体。

 

在定义结构体时不能出现类似递归的自调用,无法为结构体分配内存。若想自调用,可以通过指针实现。

例:

struct Node

{

int date;

struct Node *next;

};

 

两个结构体需互相调用时,后面定义的结构体的应在定义前面的结构体之前提前声明。

struct B;

struct A

{

int _a;

struct B* pb;

};

struct B {

int _b;

struct A* pa;

};

2.结构体初始化

结构体在初始化时可以整体赋值,但在赋值时不可以整体赋值。

简单的初始化:

struct Stu

{

char name[20];

int age;

char sex;

}a;

struct Stu a = {"zhangsan",18,'w'};

结构体嵌套初始化:

struct Point

{

int x;

int y;

};

struct data

{

int data;

struct Point p;

struct Node * next;

};

struct data d = { 12, { 1, 2 },NULL };

结构体初始化和数组一样都用{},结构体嵌套再用{}表示嵌套的结构体。

3结构体内存对齐

为什么存在内存对齐?

 1. 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能 在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2. 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的 内存访问仅需要一次访问。

 

1.第一个成员有对齐数,但不用对齐。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

VS中默认的值为8

Linux中的默认值为4

3.结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐

数)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍

处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整

数倍。

 用例子解释一下

struct S1

{                   // 对齐数

char c1;      //1

int i;           //4        

char c2;      //1   

};

c1是第一个成员不用参与对齐,但有对齐数是1

i是第二个成员,对齐数是4,此时c1应与之对齐,所以c1后空了3

c2对齐数是1,结构体总大小为最大对齐数的整数倍,此时为9c2后应空3

结构体总大小为12

 

struct S2

{

char c1;      //1

char c2;      //1

int i;            //4

};

c2c1对齐,对齐数是1,满足,紧挨c1存放。

i对齐数是4,空2个再存放i

 

struct S3

{

double d;     //8

char c;       //1

int i;        //4

};

d是第一个成员,有对齐数,不用对齐,c对齐数是1,紧挨d存放,i对齐数是4

3个再存放。最大对齐数是8

 

 

//结构体嵌套问题

struct S4

{

char c1;           //1

struct S3 s3;       //8

double d;         //8  

};

嵌套的结构体对齐到自己的最大对齐数的整数倍处

 

int main()

{

printf("%d\n", sizeof(struct S1));   //12

printf("%d\n", sizeof(struct S2));   //8

printf("%d\n", sizeof(struct S3));   //16

printf("%d\n", sizeof(struct S4));   //32

system("pause");

return 0;

}

4.位段,位段计算机大小

位段的声明和结构是类似的,有两个不同:

1.位段的成员必须是 int、unsigned int 或signed int 。

2. 2.位段的成员名后边有一个冒号和一个数字。

struct S

{

char a : 3;

char b : 4;

char c : 5;

char d : 4;

};

 

int main()

{

struct S s = { 0 };

s.a = 10;

s.b = 12;

s.c = 3;

s.d = 4;

位段元素之间相互不受影响,若存放元素时空间不够,自动舍弃,不会占用其他成员的空间,

Struct默认4自己,int

在分配空间时,在默认4字节之内连续存放,若最后一个放不下,直接开辟新的int型空间。

5.枚举+联合

1)枚举

枚举的优点

1. 增加代码的可读性和可维护性

2. #define定义的标识符比较枚举有类型检查,更加严谨

3. 防止了命名污染(封装)

4. 便于调试

5. 使用方便,一次可以定义多个常量

<1>枚举的定义

enum Day

{

Mon,

Tues,

Wed,

Thur,

Fri,

Sat,

Sun

};

Enum Day是枚举类型,MonTuesWed...是枚举成员

<2>枚举的使用

enum Day

{

Mon=1,

Tues,

Wed=2,

Thur,

Fri,

Sat,

Sun

};

int main()

{

enum Day a = Mon;

enum Day b = Tues;

enum Day c = Wed;

enum Day d = Thur;

printf("%d %d  %d  %d\n", a, b, c, d);  //1   2   2   3

system("pause");

return 0;

}

在使用枚举时,只能用枚举常量给枚举变量赋值,才不会有类型的差异

枚举成员默认从0开始取值,依次加1.

(2)联合

特点:联合体的成员共用一块内存空间,使用与结构体类似

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成 员的大小(因为联合至少得有能力保存最大的那个成员)

union Un

{

int a;

char c;

};

int main()

{

union Un U;

U.a = 0x88990011;

U.c = 0x55;

printf("%x\n", U.a);   //0x88990055

 

变量都在一块空间存放着,起始地址都是从第一字节开始。此题也可以判断大小端问题,

小端:低位在低地址 ,所以c修改的是低位,结果为0x88990055

大端:低位在高地址,高位在低地址,所以c应修改的是高位,结果应为0x55990011

联合大小的计算

联合的大小至少是最大成员的大小。 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍

例:

union Un1

{

char c[5];

int i;

};

最大对齐数是4 ,最大成员大小是5对齐到最大对齐数的整数倍,所以联合大小为8

 

union Un2

{

short c[7];

int i;

};

最大对齐数是4 ,最大成员大小是14对齐到最大对齐数的整数倍,所以联合大小为16

 

int main()

{

printf("%d\n", sizeof(union Un1));    //8

printf("%d\n", sizeof(union Un2));        //16

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值