自定义类型(结构体,位段,枚举,联合)总结

本文总结了自定义类型在编程中的应用,包括结构体的定义与使用,位段如何指定成员位数,枚举的创建以及联合在判断计算机大小端中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结构体
结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构。
结构体的定义方式:
struct 结构体名{
    结构体所包含的变量或数组
};
例如:
struct Student{      //声明一个结构体类型Student 
 int num;         
 char name[20];   
 char sex;       
 int age;         
 float score;     
};
>结构体类型的创建 
(1)先声明结构体类型再定义变量名
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


int main(){
struct Student{      //声明一个结构体类型Student 
int num;         //声明一个整形变量num 
char name[20];   //声明一个字符型数组name 
char sex;        //声明一个字符型变量sex 
int age;         //声明一个整形变量age 
float score;     //声明一个单精度型变量 
};
Student student1, student2;// 定义结构体类型变量student1和student2
printf("%d\n", sizeof(Student));
system("pause");
return 0;

}


(2)在声明类型的同时定义变量
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


int main(){
struct Student{      //声明一个结构体类型Student 
int num;         //声明一个整形变量num 
char name[20];   //声明一个字符型数组name 
char sex;        //声明一个字符型变量sex 
int age;         //声明一个整形变量age 
float score;     //声明一个单精度型变量 
}Student1,Student2;
Student student1, student2;// 定义结构体类型变量student1和student2
printf("%d\n", sizeof(Student));
printf("%d\n", sizeof(Student1));
printf("%d\n", sizeof(Student2));
system("pause");
return 0;
}
(3)直接定义结构体类型变量
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


int main(){
struct {      //声明一个结构体类型Student 
int num;         //声明一个整形变量num 
char name[20];   //声明一个字符型数组name 
char sex;        //声明一个字符型变量sex 
int age;         //声明一个整形变量age 
float score;     //声明一个单精度型变量 
}Student1,Student2;
printf("%d\n", sizeof(Student1));
printf("%d\n", sizeof(Student2));
system("pause");
return 0;
}


只能对结构体变量中的成员赋值,而不能对结构体类型赋值。

>结构体初始化 
(1)在定义结构体时对结构体变量指定初始值。
struct {      //声明一个结构体类型Student 
int num;         //声明一个整形变量num 
char name[20];   //声明一个字符型数组name 
char sex;        //声明一个字符型变量sex 
int age;         //声明一个整形变量age 
float score;     //声明一个单精度型变量 
}student1 = {
10001,
"zhangsan",
'm',
19,
"100",
};
(2)在定义变量时进行初始化
struct  Student{      //声明一个结构体类型Student 
int num;         //声明一个整形变量num 
char name[20];   //声明一个字符型数组name 
char sex;        //声明一个字符型变量sex 
int age;         //声明一个整形变量age 
float score;     //声明一个单精度型变量 
};
Student student1 = {10001,"zhangsan",'m',19,99};  //初始化


>引用结构体变量中的一个成员的值
引用方式:结构体变量名.成员名
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>


struct Student{      //声明一个结构体类型Student 
int num;         //声明一个整形变量num 
char name[20];   //声明一个字符型数组name 
char sex;        //声明一个字符型变量sex 
int age;         //声明一个整形变量age 
float score;     //声明一个单精度型变量 
};


int main()
{
Student one = { 10001, "zhangsan", 'm', 19,  100, };
printf("%d\n",one.num );
printf("%s\n", one.name);
printf("%c\n", one.sex);
printf("%d\n", one.age);
printf("%f\n", one.score);
system("pause");
return 0;
}

>结构体内存对齐 
(1)平台原因:
不是所有的硬件平台都能访问任意地址上的任意数据;某些平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常
(2)性能原因:
数据结构应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;二内存对齐的内存访问仅需要一次访问。
->结构体的对齐规则
(1)第一个成员在结构体偏移量为0的地地址处。
(2)其他成员变量要对齐到对齐数的整数倍的地址处。
对齐数=默认编译器的一个对齐数与该成员大小的较小值。(vs中默认值为8,linux中默认值为4)
(3)结构体总大小为最大对齐数的整数倍。
(4)如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是最大对齐数的整数倍。 
只看定义或许不好理解,我们看看例子 就很容易懂了
eg1
struct {
short a1;
short a2;
}A;


struct{
long a1;
short a2;
}B;


sizeof(A) = 4; //这个很好理解,两个short都为2。
sizeof(B) = 8; //这个比是不是比预想的大2个字节?long为4,short为2,整个为8,因为原则3。


eg2.
struct A{
int a;//4
char b;//1
short c;//2
};


struct B{
char b;//1
int a;//4
short c;//2
};


sizeof(A) = 8; //int为4,char为1,short为2,这里用到了原则2和原则3。
sizeof(B) = 12; //是否超出预想范围?char为1,int为4,short为2,怎么会是12?还是原则2和原则3。
这样或许还是不是很清楚那我们再看看内存布局吧(用*代表填充的字节) 
先看看A的内存布局


这里b后面为何要补充一个字节?因为c为short,其起始位置要为2的倍数,就是原则2。c的后面没有补充,因为b和c正好占用4个字节,整个A占用空间为4的倍数,也就是最大成员int类型的倍数,所以不用补充。
再看看B的内存布局



这里b是char为1,b后面补充了3个字节,因为a是int为4,根据原则2,起始位置要为4的倍数,所以b后面要补充3个字节。c后面补充两个字节,根据原则3,整个B占用空间要为4的倍数,c后面不补充,整个B的空间为10,不符,所以要补充2个字节。
->再看结构体嵌套情况
eg3
struct S3
{
double a;
char b; 
int c;
};
struct S4
{
char c1;
struct S3 s3;
double d;
};
sizeof(S3) = 16;// //这个比较好理解,double为8,char为4,int为4,总长为8的倍数,补齐,所以整个A为16
sizeof(S4) = 32;

在这里c1是char,c1后面补充了7个字节,因为s3的最大对齐数为8,根据规则2,起始位置要为8的倍数,所以c1后面补充了7个字节,后面d也是8个字节,总大小是8的倍数,不用再加。
我们再看看一个复杂点的
eg4
int main()
{
struct S3
{
double a;
char b;
int c;
};
struct S4
{
char c1;
struct S3 s[3];
char ch[5];
struct s3 *p;
double b;
short d[3];
};
printf("%d\n", sizeof(struct S4));
system("pause");
return 0;

}//88


结构体的内存对齐就是拿空间换取时间的做法。
>位段,位段计算机大小。 
位段,C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为"位段"或称"位域"( bit field) 。利用位段能够用较少的位数存储数据。
1.位段的成员必须是int,unsigned int,signed int。

2.位段的成员名后边有一个冒号和一个数字,这个数字指定该位段所占用的位的个数。例如:


位段的跨平台问题:
(1)int位段被当成有符号数还是无符号数是不确定的。
(2)位段中最大位的数目不确定(16位机器最大16,32位机器最大32,写成27在16位机器会出问题)。
(3)位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
(4)当一个机构包含两个位段,第二个位段成员比较大,五福容纳与第一个位段剩余的位时,是舍弃还是利用,这是不确定的。
>枚举  就是把可能的取值一一列举出来。
Eg:
enum Day
{
Mon,
Tues,
Wed,
Thur,
Fri,
Say,
Sun
};
枚举的特点:
(1)增加代码的可读性和可维护性;
(2)跟#define定义的标识符比较枚举有类型的检查,更加严谨
(3)防止命名污染
(4)便于调试
(5)使用方便,一次可以定义多个常量
>联合
联合也是一种特殊的自定义类型
联合说明和联合变量定义与结构十分相似,其形式为:
union 联合名
{
数据类型成员名
};
联合变量名联合表示几个变量公用一个内存位置, 在不同的时间保存不同的数据类型和不同长度的变量(至少是最大成员的大小)。例如:

联合也可以用来判断计算机的大小端存储:


 联合也是需要内存的对齐。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值