C语言中的数据封装特性
1、在C语言中基础数据封装主要有结构体(struct)、联合体(union)、枚举类型(enum)
1、定义:
结构体:是由一些具有相同类型、或者不同类型的数据组成的数据集合;
联合体:在需要将不同的数据类型储存在同一段内存单元中。也是说覆盖技术,几个变量相互覆盖。这些不同类型变量存放在同一段内存结构。
具有这种结构的数据类型,被称作联合体。
2、结构数据的长度区别
结构体类型数据长度:一个结构体变量的长度是各个成员长度之和;
联合体类型数据长度:一个联合体变量的长度等于成员中最长的那个;(存在数据对齐)
3、结构中元素内存分配情况
结构体:结构体名是结构体第一个地址,也就是首成员相对第一地址的偏移量为0,以后每个数据成员按照指定的偏移地址偏移;
联合体:联合体中数据成员完成对齐之后,按照分配内存空间最大的成员存储数据;
4、使用程序说明:
// 测试程序 #include <stdio.h> // 定义一个学生的结构体 typedef struct student{ int num; // 4 char name[64]; // 64字节 char name1; // 1字节 double hight; // 8字节 float f; // 4字节 int age; // 4字节 // 排序时候,存在数据对齐,不是4+64+1+8+4+4 }stu; // 定义一个联合体classes typedef union classes // 不是class类 { char name[51]; // 51字节 int age; // 4字节大小 double height; // 8字节 }classes; void main() { stu s; classes u; // 打印常见的数据类型占用内存的大小 printf("sizeof double is %d\n",sizeof(double)); printf("sizeof int is %d\n",sizeof(int)); printf("sizeof is %d\n",sizeof(float)); // 结构体stu占用的内存大小 printf("sizeof struct is :%d\n",sizeof(s)); // 打印结构体成员地址 printf("address struct stu:%x\n",&s); printf("address struct stu.num:%x\n",&s.num); printf("address struct stu.name[64]:%x\n",(s.name)); printf("address struct stu.name1:%x\n",&(s.name1)); printf("address struct stu.f:%x\n",&(s.f)); printf("address struct stu.gae:%x\n",&(s.age)); // 打印联合体成员地址 printf("sizeof union is :%d\n",sizeof(u)); printf("address union u:%x\n",&u.name); printf("address union u:%x\n",&u.age); printf("address union u:%x\n",&u.height); printf("hello world\n"); getchar(); }
输出结果:
sizeof double is 8 sizeof int is 4 sizeof is 4 // 结构体大小 sizeof struct is :88 // 结构体地址 address struct stu:113fbd4 address struct stu.num:113fbd4 address struct stu.name[64]:113fbd8 address struct stu.name1:113fc18 address struct stu.f:113fc24 address struct stu.gae:113fc28 // 联合体大小 sizeof union is :56 // 联合体地址 address union u:113fb94 address union u:113fb94 address union u:113fb94 hello world
2、关键修饰符static、const、volatile
static:
1、修饰局部变量:
1、用于延长变量的生命周期:相对于普通局部变量,是保存在栈上,函数一旦退出或者结束,变量就会被释放掉;二次访问的会出现新的初始值;使用static关键字修饰后的变量,该变量始终保存在静态的数据段中;直到整个程序退出,该变量才被释放;
2、局部变量的静态化:局部变量保存在栈上,被修饰后,局部变量保存在静态的数据段;
2、修饰全局变量:
主要防止重命名,主要用于多文件编程,也就是限制作用域;被修饰函数的作用域限制在当前文件;
3、修饰全局函数名称:
限制函数名称重命名,限制函数只在该文件的访问权限;
const:
1、对于C语言编译器,修饰的变量的表面是只读属性,但是只是建议性的,并不具备强制性;也就是说const int a =20;修饰的变量a编译器建议不修改,但是可以使用指针修改a的值;
2、对于C++编译器,const修饰的变量就是只读属性,不可以修改,C++语法相对于C语法更严谨;
volatile:
表明该变量可能被外界修改,不需要编译器做优化;可能修饰寄存器相关、中断相关、多线程相关;
对于volatile关机键字可以从反汇编角度看:
// 对于同一段代码 int func1(int* p) { return (*p == *p); } int func2(volatile int* p) { return (*p==*p); }
编译以反汇编后:可以看出func1中直接返回结果,func2中取了两次值,并比较寄存器中的值cmp(使用的编译器可能存在差异,结果稍微不同)
arm-none-linux-gnueabi-gcc -c test.c -o test.o arm-none-linux-gnueabi-objdump -D test.o // 显示在屏幕上,如下图

3、define宏定义一个模块
#define myStruct (struct stu*) typedef struct stu* myS; myStruct stu1, stu2; --->struct stu* stu1, stu2; myS stu1, stu2; --->struct stu* stu1, *stu2;
从上面列子可以看出来,define和typedef之间存在这样的差异;

浙公网安备 33010602011771号