C语言自定义类型的保姆级讲解

前言

在我们日常写代码时,经常会遇到结构体类型的使用,今天带读者了解结构体类型的使用。

一、初始结构体

在了解结构体之前,我们先来了解一下结构体的基础只是,结构体到底是什么?

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

下面举一个例子:

struct tag
{
 menber_list; //成员列表
}variable_list; //变量列表

例如我们使用结构体描述一台电脑

struct computer
{
 int price;//价格
 char name[20];//名称
 char brand[10];//品牌
 }computer; //需要注意的是最后一行的“ ;”不能丢哦,不然编译器会报错提示你。

结构成员的类型

结构成员可以是标量数组、指针、甚至可以是其他的结构体。

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

匿名结构体类型

//匿名结构体类型
struct
{
 int a;
 char b;
 float c;
}x;
struct
{
 int a;
 char b;
 float c;
}a[20], *p;

上面的代码中结构体省略掉了结构体标签,我们在添加一行代码

p=&x;

当我们编译时,会发现这样两个错误。

所以这样是不可行的。

结构体的自引用

就像函数递归一样,结构体也可以自己引用自己。他们的格式是这样的。

struct Node
{
 int data;
 struct Node* next;
};

结构体变量的定义和初始化

struct stu
{
	char name[20];
	int age;

};
struct stu s = { "Geralt ",100};

利维亚的杰洛特,100岁!

结构体内存对齐

各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数 各成员变量在存放的时候根据在结构中出现的顺序依次申请空间 同时按照上面的对齐方式调整位置 空缺的字节自动填充 同时为了确保结构的大小为结构的字节边界数(即该结构中占用最大的空间的类型的字节数)的倍数,所以在为最后一个成员变量申请空间后 还会根据需要自动填充空缺的字节。

简单的说就是:结构体的内存对齐是拿空间来换取时间的结果,提高了效率,浪费少许空间。

规则如下:

  1. 第一个成员在与结构体变量偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
    对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
  3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

VS编译器中默认对齐数是8。

当然了,作为创建VS,Linux的我们是可以在C语言中自定义对齐数的。

我们可以使用#pragma这个预处理指令修改默认对齐数。

Eg:#pragma pack(4) //修改对齐数为4

结构体传参

struct s
{
	int data[1000];
	int num;
};
struct s s = { {1,2,3,4},100 };
//结构体传参
void print1(struct s s)
{
	printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct s* ps)
{
	printf("%d\n", ps->num);
}

int main()
{
	print1(s);
	print2(&s);

	return 0;

和函数传参一样,形参是实参的一份临时拷贝,参数是需要压栈,会有时间和空间上的系统开销,如果传递的过程中结构体过大,就可能会导致系统开销大,导致性能的下降。我们不如直接传过去一份地址,再对它进行解引用操作符。

二、位段

位段与结构体不同的地方在于声明的时候,1.位段的成员必须是 int、unsigned int 或signed int 。2.位段的成员名后边有一个冒号和一个数字。

举一个例子:

struct A
{
int _a:2;

int _b:5;
int _c:10;
int _d:30;
};
  1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
  2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
  4. 举一个例子
struct S
{
char a:3;
char b:4;
char c:5;
char d:4;
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;

那么位段的空间是如何开辟的呢?一张图搞定!

总的来说,位段和结构体相似,可以更好的节省空间,但是位段有跨平台的问题存在。

三、枚举

枚举枚举,顾名思义就是把可能出现的取值一一列举出来。

比如我们要描述一年的月份:

可以一一列举,我们要描述计算机语言的类型,也可以一一列举。

下面举一个例子

代码如下(示例):

enum ComputerLangue
	{
		C,
		Java,
		Python,

	};

每种结构体都有一定的优点,那么枚举有什么优点呢?

  1. 增加代码的可读性和可维护性
  2. 和#define定义的标识符比较枚举有类型检查,更加严谨。
  3. 防止了命名污染(封装)
  4. 便于调试
  5. 使用方便,一次可以定义多个常量

联合(公用体)

联合的特点是成员们公用同一块空间,因此他们也可以叫共用体

代码如下(示例):

//联合类型的声明

union Un
{
 char c;
 int i;
};
//联合变量的定义
union Un un;
//计算连个变量的大小
printf("%d\n", sizeof(un));

三、 练习

在VC2013这款编译器中,这个结构体所占的空间大小是多少字节?

typedef struct{
 int a;
 char b;
 short c;
 short d;
}AA_t;

答案是:12个字节

为什么呢?结构体判断大小,一般向成员中最长的元素对齐。

在这4个结构成员中,最长的元素为a占四个字节。所以其他元素要向四对齐。a单独占四个字节,b为char类型占一个字节,c为short和b一起占四个字节并且空出一个字节。剩下d占一个字节,空两个字节。所以总占空间大小是4+1+2+2+3=12字节。

struct A
{
 int a;
 short b;
 int c;
 char d;
};
struct B
{
 int a;
 short b;
 char c;
 int d;
};

我们在来看一道题 :在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是( )

答案是:16、12

最长的结构成员为int 占4个字节,b占两个字节,空下两个字节,c占4个字节,d占一个字节,空3个字节。

最长的类型为int,a占4字节,b和c一起占三个字节,还空下一个字节,d占4字节。

所以sizeof(A)sizeof(B)分别是16 12.

总结

我们介绍了C语言中的自定义类型,结构体,联合,枚举,位段,这些自定义类型可以帮我们更高效的使用C语言。

(0)

相关推荐

  • C语言自定义类型的保姆级讲解

    前言 在我们日常写代码时,经常会遇到结构体类型的使用,今天带读者了解结构体类型的使用. 一.初始结构体 在了解结构体之前,我们先来了解一下结构体的基础只是,结构体到底是什么? 结构是一些值的集合,这些值称为成员变量.结构的每个成员可以是不同类型的变量. 下面举一个例子: struct tag { menber_list; //成员列表 }variable_list; //变量列表 例如我们使用结构体描述一台电脑 struct computer { int price;//价格 char name

  • C语言自定义类型详解(结构体、枚举、联合体和位段)

    目录 前言 一.结构体 1.结构体类型的声明 2.结构体的自引用 3.结构体变量的定义和初始化 4.结构体内存对齐 5.结构体传参 二.位段 1.位段的定义 2.位段的内存分配 3.位段的应用 三.枚举 1.枚举类型的定义 2.枚举的优点 3.枚举的使用 四.联合体(共用体) 1.联合体的定义 2.联合体的特点 3.联合体的大小计算 总结 前言 一.结构体 1.结构体类型的声明 当我们想要描述一个复杂变量--学生,可以这样声明. ✒️代码展示: struct Stu { char name[20

  • C语言自定义类型全解析

    目录 前言 结构体类型 结构体的声明 结构体变量的定义与初始化 结构体的自引用 结构体的访问 结构体的传参 传结构体 传地址 结构体的内存对齐(强烈建议观看) 位段 位段的声明 位段的内存管理 位段的跨平台性  枚举类型 枚举类型的定义 枚举类型赋予初始值 枚举类型的优点 联合体类型 联合体的定义 联合体的特点  联合体内存大小的计算 前言 初学C语言 我们先接触的都是内置的类型 比如说int char short float double long等等 这一期就来聊一聊自定义类型的知识 结构体

  • C语言自定义类型超详细梳理之结构体 枚举 联合体

    目录 一.什么是结构体 1.结构体实现 2.匿名结构体类型 3.结构体自引用 4.结构体的内存对齐 5.结构体位段  二.什么是枚举 1.枚举类型的定义 2.枚举的优点 三.联合(共用体) 1.什么是联合(共用体) 2.联合(共用体)的定义 3.联合(共用体)的初始化 总结 一.什么是结构体 结构是一些值的集合,这些值称为成员变量.结构的每个成员可以是不同类型的变量. //结构体声明 struct tag //struct:结构体关键字,tag:标签名,合起来是结构体类型(类型名) { memb

  • C语言 自定义类型全面系统理解

    目录 一.结构体 1.结构体的声明 局部结构体变量 全局结构体变量 2.特殊声明 3.结构体的自引用 4.结构体变量的初始化 5.结构体内存对齐  6.修改默认对齐数 7.结构体传参 传址调用原因: 二.位段 举例: 分析: 跨平台问题: 三.枚举 枚举类型的定义: 枚举的优点  四.联合 1.联合类型的定义 2.联合的特点  使用案例: 分析: 3.联合大小的计算  举例: 分析: 一.结构体 结构体是不同类型变量的集合体 1.结构体的声明 struct Book { char name[20

  • Vue中四种操作dom方法保姆级讲解

    目录 前言 一.通过ref拿到dom的引用 适用场景 示例代码 二.通过父容器的ref遍历拿到dom引用 适用场景 示例代码 三.通过子组件emit传递ref 适用场景 示例代码 四.通过:ref将dom引用放到数组中 适用场景 示例代码 前言 最近主管提出了许多优化用户体验的要求,其中很多涉及 dom 操作.本文将 Vue3 中常见的 dom 操作总结了一下. 一.通过ref拿到dom的引用 <template> <div class="ref-container"

  • C语言:自定义类型详解

    目录 一.结构体 1.结构体变量的定义及初始化 2.结构体内存对齐 3.为什么要内存对齐呢? 二.位段 1.什么是位段 2.位段的内存分配 三.枚举 1.枚举的定义 2.枚举的优点 四.联合(共用体) 1.联合类型的定义 2.联合的特点 3.联合大小的计算 总结 一.结构体 1.结构体变量的定义及初始化 直接上代码: struct Point { int x; int y; }p1; //创建结构体时顺便创建变量,分号一定不能掉 struct Point p2; //单独创建变量 struct

  • C语言中自定义类型详解

    目录 结构大小 offsetof 结构体对齐规则 存在原因 总结 结构大小 我们先随便给出一个结构体,为了计算他的大小,我给出完整的打印方案: typedef struct num { char c; int n; char cc; }num; int main() { printf("%d\n", sizeof(num)); return 0; } 好了,按道理来说我计算一个结构体大小就看他的各个成员需要消耗多大的空间, num 结构体中三个成员分别是 char ,int ,char

  • C语言中的自定义类型之结构体与枚举和联合详解

    目录 1.结构体 1.1结构的基础知识 1.2结构的声明 1.3特殊的声明 1.4结构的自引用 1.5结构体变量的定义和初始化 1.6结构体内存对齐 1.7修改默认对齐数 1.8结构体传参 2.位段 2.1什么是位段 2.2位段的内存分配 2.3位段的跨平台问题 2.4位段的应用 3.枚举 3.1枚举类型的定义 3.2枚举的优点 3.3枚举的使用 4.联合 4.1联合类型的定义 4.2联合的特点 4.3联合大小的计算 1.结构体 1.1结构的基础知识 结构是一些值的集合,这些值称为成员变量.结构

  • 详解C语言随机数设置的三种方式(保姆级教程)

    目录 前言 随机数设置三板斧 第一式:rand函数 第二式:srand函数 第三式:time函数 前言 本篇文章将为大家介绍在C语言中如何设置随机数,在设置随机数的过程中,大家可能会遇到以下问题: 1.每次进入程序后的随机数与上一次相同. 2.当随机数设置过快时,可能会相同. 3.如何设置指定范围的随机数. 随机数设置三板斧 在设置随机数的时候,我们需要用到三个函数,它们分别是rand,time,srand.下面将一一进行讲解: 第一式:rand函数 我们可以打开MSDN去看看rand函数的定义

随机推荐