自定义类型:结构体、枚举、联合
2017-11-26 11:47
411 查看
结构体
定义和初始化:
基本定义:结构体,通俗讲就是打包封装,把一些有共同特性(或属于同一类事物的属性)的变量放在其内部,通过一定方法访问修改内部变量。
结构体的定义方式还有很多种:
1、只有结构体:
struct stu { char name[20]; int age; float height; };
2、附加结构体类型的变量的定义:
struct stu { char name[20]; int age; float height; }S;
3、简略结构体后面的名字:
struct { char name[20]; int age; float height; }S;
4、
添加指针指向结构体变量
struct stu { char name[20]; int age; }S,*p;
初始化:
struct stu { char name[20]; int age; }S; struct stu S = { "haha", 18 };
结构体嵌套初始化 :
struct node { int data; struct point p; struct node *next; }n1 = { 10, { 4, 5 },NULL }; struct n2 = { 20, {5,6} 18 };
结构体的自引用:
struct node { int data; struct node* next; };
看到这个,是不是想起了数据结构中的链表呢?
知道第一个结点,通过指针可以找到后面所有的结点。
结构体的成员:
结构体的成员可以是标量、指针、数组、甚至是其他结构体那么如何访问其成员呢?
》点操作符
struct stu { char name[20]; int age; }; struct stu s; strcpy(s.name, "haha"); s.age = 19;
》指向操作符
struct stu { char name[20]; int age; }S; void print(struct S* sp) { printf("name=%s age=%d", (*sp->name, *sp.age)); }
结构体内存对齐:
1、对齐规则:i)第一个成员无须偏移(但是他也具有对齐数)。
ii)其他成员变量要对齐到一个数的整数倍处(这个数是对齐数)
vs中默认为8,Linux默认为4
iii)结构体的大小是最大对齐数的整数倍。
iv)嵌套结构体时,嵌套的结构体对齐到自己最大对齐数的整数倍,所以整个结构体的大小就是所有最大对齐数(嵌套的结构体对齐数也在内)的整数倍。
例题:
1、
struct s1 { char c1; int i; char c2; }; int main() { printf("%d\n", sizeof(struct s1)); system("pause"); return 0; }
2、
3、
4、结构体嵌套问题
为什么存在内存对齐?
1、平台原因(移植原因)
不是所有的硬件平台都能访问任意地址上的任意数据;有些平台只能在某些地址处取某些特定类型的数据,否则抛出异常。
2、性能原因
数据结构(尤其是栈)应该尽可能在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器要两次访问;而对齐则只需一次访问。
**总体来说,结构体的内存对齐就是以空间来换时间的做法,所以我们在设计结构体时,要把占用空间小的量尽量放在前面。
结构体传参
结构体传参的时候要传结构体的地址struct S { int data[1000]; int num; }; struct S s = { { 1, 2, 3, 4 }, 1000 }; //void p 4000 rint1(struct S s) //{ // printf("%d\n", s.num); //} void print2(struct S* ps) { printf("%d\n", ps->num); } int main() { //print1(s);//传结构体 print2(&s);//传地址 system("pause"); return 0; }
上面的两种传参方式,首选传地址,这就和我们函数传参形成栈帧有关了,如果直接传一个结构体对象,假如结构体很大,那么压栈开销就会很大,导致性能的下降,在这个例子中,他结构体中还有数组,所以传结构体对象时数组不会传过去,而是会一遍遍实例化数组,所以开销是非常大的。
结构体实现位段:
位段的声明和结构体类似,1、位段的成员必须是int、unsigned int、或者signed int。2、位段的成员名后面有一个冒号和一个数字。比如:struct A { int _a : 2; int _b : 5; int _c : 10; int _d : 30; };
所以A需要两个int,大小就是8字节
再例如:
位段的内存分配:
1、位段的成员必须是位段的成员必须是int、unsigned int、或者signed int或者char(整型家族) 2、位段的空间是按照4字节(int)或者1字节(char)的方式来开辟的。 3、位段涉及很多不确定因素,不跨平台
不跨平台的原因:
int 是有符号还是无符号是不确定的。
位段中最大位的数目不确定。(16位机器是16,32位机器是32)。
位段中成员在内存中从左向右分配,还是从右向左不确定
当一个结构有两个位段,第二个位段成员比较大,无法容纳第一个位段剩的位时,是舍弃剩余的位还是利用,也是不确定的。
枚举
一 一列举。定义:
enum day { sun, mon, tues, wed, thur, fri, sat, };
定义一个周从星期天到星期六是枚举。{}中的内容是枚举类型的可能取值,也叫枚举常量,这些取值都是有值的,默认从零开始,每次递增一
使用:
只能用枚举常量给枚举变量赋值:enum day { sun, mon, tues, wed, thur, fri, sat, };
enum day d = sun;
d = 0;
优点:
1、增加代码可读性和可维护性。 2、与define定义的宏相比他有类型检查。 3、防止明名污染(封装)。 4、便与调试。 5、使用方便,一次可定义多个常量。
联合(共用体)
定义:
联合定义的变量包含一系列的成员,特征是这些成员共用同一块空间。使用:
联合的成员是共用一块空间的,所以一个联合变量的大小,至少是最大成员的大小(因为联合至少有能力保存最大的那个成员)。下面的代码输出结果相同,可以看出,成员确实共用一块空间。
union Un { int i; char c; }; int mian() { union Un un; printf("%d\n", &(un.i)); printf("%d\n", &(un.c)); printf("%d\n", &(un)); system("pause"); return 0; }
应用:
判断计算机的大小端存储:
#include<stdio.h> union Un { int i; char c; }; int mian() { union Un un; un.i = 0x11223344; un.c = 0x55; printf("%x", un.i); system("pause"); return 0; }
输出结果为:0x11223355由于我的计算机是小端存储,而c占i4个字节的低位,低地址放在低位就是小端存储。
计算联合变量的大小:
联合的对齐:
~联合的大小至少是最大成员的大小。
~当最大成员不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。
#include<stdio.h> union Un1 { int i; char c[5]; }; union Un2 { short c[7]; int i; }; int mian() { printf("%d\n",sizeof(union Un1));//8 printf("%d\n", sizeof(union Un2));//16 system("pause"); return 0; }
相关文章推荐
- 自定义类型(结构体,位段,枚举,联合)总结
- 自定义类型(结构体、枚举、联合)以及内存对齐问题
- 自定义类型——结构体、枚举、联合
- 自定义类型——结构体,枚举,联合
- 自定义类型:结构体 位段 枚举 联合
- 自定义类型:结构体、枚举、联合
- 自定义类型:结构体,枚举,联合
- 自定义类型(结构体,枚举,联合,位段)
- 自定义类型(结构体、位段、枚举和联合)
- 自定义类型:结构体,枚举,联合部分知识总结
- 自定义类型:结构体,枚举,联合
- 自定义类型:结构体,枚举,联合体
- C++之 自定义数据类型 枚举、结构体、共用体
- 结构体struct、枚举enum、联合体union、位字段、自定义类型typedef、字节对齐
- Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型
- Android For JNI(五)——C语言多级指针,结构体,联合体,枚举,自定义类型
- 自定义类型部分知识写一篇博客。 知识点: >结构体类型创建 >结构体初始化 >结构体内存对齐 >位段,位段计算机大小。 >枚举+联合。
- 自定义类型中结构体、枚举等,结构体内存对齐相关要点总结
- 自定义类型:结构体,枚举,联合体
- C++ 自定义数据类型:结构体,共用体,枚举