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

 更新时间:2021年03月09日 12:18:32   作者:teacher dsma  
这篇文章主要给大家介绍了关于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语言。

相关文章

  • 关于C语言位运算的简单示例

    关于C语言位运算的简单示例

    这篇文章主要介绍了关于C语言位运算的简单示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • C++ 详解数据结构中的搜索二叉树

    C++ 详解数据结构中的搜索二叉树

    搜索二叉树是一种具有良好排序和查找性能的二叉树数据结构,包括多种操作,本篇只介绍插入,排序(遍历),和删除操作,重点是删除操作比较复杂
    2022-04-04
  • 基于Matlab实现抖音小游戏苹果蛇

    基于Matlab实现抖音小游戏苹果蛇

    最近抖音上苹果蛇小游戏大火,为了证明MATLAB无所不能,咋能不跟风做一个?文中详细讲解了游戏的实现步骤,感兴趣的小伙伴可以尝试一下
    2022-06-06
  • 编辑器写C语言输出中文乱码问题及解决

    编辑器写C语言输出中文乱码问题及解决

    这篇文章主要介绍了编辑器写C语言输出中文乱码问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • C语言新手练习题之求第n个斐波那契数

    C语言新手练习题之求第n个斐波那契数

    斐波那契数列这一个大一上C语言就有的问题大家应该都不陌生,下面这篇文章主要给大家介绍了关于C语言新手练习题之求第n个斐波那契数的相关资料,文中通过图文以及实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • C++实现KDTree 附完整代码

    C++实现KDTree 附完整代码

    这篇文章主要介绍了C++实现KDTree的代码详解,包括kdTree概念介绍及分割的作用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07
  • C语言实现推箱子游戏完整代码

    C语言实现推箱子游戏完整代码

    这篇文章主要为大家详细介绍了C语言实现推箱子游戏完整代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • Mac OS上搭建Apache+PHP+MySQL开发环境的详细教程

    Mac OS上搭建Apache+PHP+MySQL开发环境的详细教程

    这篇文章主要介绍了Mac OS上搭建Apache+PHP+MySQL开发环境的详细教程,包括常见的PHP连接MySQL失败问题的解决办法,需要的朋友可以参考下
    2016-01-01
  • 配合ffmpeg接口获取视频音频媒体信息详解

    配合ffmpeg接口获取视频音频媒体信息详解

    这篇文章主要为大家介绍了配合ffmpeg接口获取视频音频媒体信息详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • C语言中的内存泄露 怎样避免与检测

    C语言中的内存泄露 怎样避免与检测

    堆经常会出现两种类型的问题:1.释放或改写仍在使用的内存(称为:“内存损坏”)。2.未释放不再使用的内存(称为:“内存泄露”)。这是最难被调试发现的问题之一
    2013-09-09

最新评论