自定义数据类型struct,enum,union的使用
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了自定义数据类型struct,enum,union的使用,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7606字,纯文字阅读大概需要11分钟。
内容图文
![自定义数据类型struct,enum,union的使用](/upload/InfoBanner/zyjiaocheng/1002/6bc0be3d2bad47369371011ac29674d7.jpg)
一、.结构体:从来存放表示某种特定含义的一组数据
特点:它是对数据封装(函数是对功能封装)
好处:1.提高代码的可读性
2.提高数据易用性
3.提高代码可维护性
结构体定义格式:
struct +结构体名
{
元素1;
.....
}
结构体定义结构体变量:
struct +结构体名+变量名(c语言下),
结构体名+变量名(c++下)。
内存对齐:
意义:以空间换时间,避免内存的二次读取,可以减少cpu访存的次数。
方法:
1.从第一个属性开始,内存从0开始,第二个属性应放在min(该属性的大小,对齐模数)的整数倍上。
2.当所有属性计算完成后,整体做二次偏移,当所有的属性偏移完成后,取min(该结构体最大元素,对齐模数)的整数倍。
注:
1.变量的起始内存必须是它的整数倍,比如char a;占一个字节,但是后跟int类型数据,所以此时只能从4的整数倍开始,造成了本占一个字节的数据占了4字节
2.所占的字节数并非一成不变的,可以通过修改默认情况下的对齐模数,达到修改所占内存大小的目的。
eg:
struct student
{ 第一次偏移 第二次偏移(起始内存必须是min(当前类型大小,对齐模数)整数倍)
char a;// 0 0-3(因为要保证b的地址必须从4开始)
int b;// 1-4 4-7
double c;// 5-12 8-15
}
故对齐后为16字节大小。
当调换元素顺序时,其大小可能会发生改变
struct student
{ 这边直接给值,不写分析步骤
int b; //0-7
double c; //8-15
char a; //16 此时占17个字节,故结果为24字节(内存对齐)
}
//故在定义结构体时在没有特殊需求的情况下,元素应从小到大进行定义
一个结构体的自身所占内存大小并非是一成不变的,可以通过修改对齐模数达到修改所占内存的目的。
格式:#pragma pack(num)//num是用户字节给出的
#pragma pack(show)//可以查看本机的对齐模数,默认是8
eg:
#pragma pack(1)
struct student
{
char a;//0
int b;//1-4
double c;//5-12
}//在对齐模数为1的情况下,此时占13个字节。
c语言结构体与c++结构体的区别:
1.c++下,在定义结构体变量时可以省略struct关键字。
2.c++下,结构体中可以定义成员函数
3.c++下,结构体是可以被另一结构体所继承的,默认为公有继承。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
//c++中结构体内是可以包含成员函数的
struct student
{
int age;
char name[20];
void show();//可以在结构体内声明,类外定义,也可以直接放在结构体内部
};
//c++中结构体是可以被继承的,默认情况下为公有继承
struct teacher :student
{
double score;
};
void student::show()//有一个隐含的this指针,指向该部分空间
{
/*printf("姓名%s\t", name);
printf("年龄%d\n", age);*/
printf("姓名%s\t", this->name);
printf("年龄%d\n", this->age);
}
void test01()
{
cout << sizeof(student) << endl;//结论:在存在其他元素时,此时函数不占任何空间,但一个结构体中只有一个函数时,此时会占1字节
student t1 = { 10,"张三" };//结构体变量定义时可以不加struct关键字
t1.show();
}
void test02()
{
cout << sizeof(teacher) << endl;//此时值为32=24+8.类似于将stdent元素也计算进去
teacher t;//t变量可以调用继承来的结构体的任意变量,包括它的成员函数
t.age = 10;
strcpy(t.name, "张三");
t.score = 90.0;
t.show();
}
int main()
{
//test01();
test02();
system("pause");
return 0;
}
在嵌套结构体时区分c与c++的区别
struct teacher
{
char c;//4
struct tt
{
int a;//4
char d;//4
};
int age;//4
};//在c语言下其sizeof()值是16,在c++下其值为8,编译器不将嵌套的tt
分配内存。
//注:当嵌套其中的结构体是一个未命名的结构体,此时c/c++sizeof结果是相同的。
二、offsetof()的使用
目的:求结构体中成员地址相对于结构体第一个值首地址走过的字节数。
struct student
{
int b; //0-7
double c; //8-15
char a;
};
int main(void)
{
struct student t1 = { 10,20.0,'a' };
int len = offsetof(struct student, a);
printf("%c\n", *(char*)((char*)(&t1) + len));//从左向右第二个(char*)(&t1)+len是让其逐字节位移,
//找到后第一个char*是类型转换,解引用后求出它的值
//printf("%d\n", sizeof(struct student));
system("pause");
return EXIT_SUCCESS;
}
三、位域(位段的概念)
引入位域的原因:
有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>
//引入位域的原因:有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。
//例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便
//,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,
//并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
struct student
{
char a : 2;
char b : 4;
};
//1.一个位域必须存储在同一个字节中,不能跨两个字节
struct t
{
int a : 5;
int b : 5;
};
//2.位域可以没有名称,示意这部分空间不可使用
struct t1
{
int a : 30;
int : 2;
int b : 2;
};
//3.位域的长度不可以大于数据类型一个字节的长度 eg:int a:33;//err
//4.所有位域不可以跨类型存储,类型必须一致
struct t2
{
/*int a : 2;
char b : 2;
int c : 20;*///当看到不同类型的位域出现时,此时系统默认该位域已结束,此时sizeof求值为12
int a : 2;
int c : 20;
char b : 2;
};
void test01()
{
printf("%d\n", sizeof(struct student));
printf("%d\n", sizeof(struct t));
printf("%d\n", sizeof(struct t1));
printf("%d\n", sizeof(struct t2));
}
int main(void)
{
test01();
system("pause");
return EXIT_SUCCESS;
}
三、枚举enum
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>
enum a {
mon,
tus,
wed,
thur,
fri,
satur,
sun,
};
void test01()
{
printf("%d\n", sizeof(enum a));//1.枚举中无论有多少个元素,其大小皆为4,或者不改变。
//枚举在编译阶段将名字替换成对应的值。我们可以将枚举理解为编译阶段的宏。
//2.枚举默认情况下元素从0开始,依次递增。
enum a t1=0;
for (size_t i = 0; i < 7; i++)
{
printf("%d\t", t1++);
}
}
//enum 搭配switch语句使用
void test02()
{
enum a t1 = mon;
while(1)
{int n=scanf("%d", &t1);
if (n == 0)
{
printf("输入类型不符合,跳出循环\n");
return;
}
switch (t1)
{
case mon: {printf("1\n"); break; }
case tus: {printf("2\n"); break; }
case wed: {printf("3\n"); break; }
case thur: {printf("4\n"); break; }
case fri: {printf("5\n"); break; }
case satur: {printf("6\n"); break; }
case sun: {printf("7\n"); break; }
default: {printf("error number\n"); continue; }
}
}
}
int main(void)
{
//test01();
test02();
system("pause");
return EXIT_SUCCESS;
}
四、共用体的使用union
因为写不动了,相应概念会在代码中呈现
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <Windows.h>
//共用体:
//特点:共用体大小永远是共用体中最大元素的值
// 共用体在一段时间内仅有一个元素有效,一个元素失效
// 共用体也必须考虑内存对齐的问题
union a
{
int a;
char c;
};
//共用体与struct区别:
//联合的所有成员引用的是内存中的相同位置。当你想在不同时刻把不同的东西存储于同一位置时,就可以使用联合。
//结构体(struct)中所有变量是“共存”的——优点是“有容乃大”,全面;缺点是struct内存空间的分配是粗放的,不管用不用,全分配。
//而联合体(union)中是各变量是“互斥”的——缺点就是不够“包容”;但优点是内存使用更为精细灵活,也节省了内存空间。
//结构体在一个时刻可以调用所有变量,而共用体不可以,只可以一个有效,一个失效。
void test01()
{
union a s1;
s1.a = 10000;//0010 0111 0001 0000
printf("%d\n", s1.c);//此时c是16 0001 0000
}
//利用共用体判断大小端
void test02()
{
union a s1;
s1.a = 1;
if (s1.a & 1 == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
}
//利用内存中的存储方式判断大小端
void test03()
{
int a = 0x01;
if (a && 1)
{
printf("xiao\n");
}
else
{
printf("da\n");
}
}
int main(void)
{
//test01();
//test02();
//test03();
typedef struct {
int a;
char b;
short c;
short d;
}AA_t;
printf("%d\n",sizeof(AA_t));
system("pause");
return EXIT_SUCCESS;
}
内容总结
以上是互联网集市为您收集整理的自定义数据类型struct,enum,union的使用全部内容,希望文章能够帮你解决自定义数据类型struct,enum,union的使用所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。