C语言——自定义类型详解[结构体][枚举][联合体]

这篇具有很好参考价值的文章主要介绍了C语言——自定义类型详解[结构体][枚举][联合体]。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:

我打算把结构体、枚举、联合体的重点内容总结一下,方便后期复习的时候能够更快,更准确的去拾取遗忘的知识。也希望能给大家起到借鉴的作用,不足的地方,请多多包涵。(不足的地方,也希望大家能够指出来)

一、结构体

1.1结构体的声明

结构体是一些值的集合,这些集合称为成员变量,结构体的每个成员可以是不同类型的变量。
结构体的声明:
C语言——自定义类型详解[结构体][枚举][联合体],C语言,c语言,算法,开发语言
结构体特殊声明:匿名结构体
如:

struct
{
int a;
char b;
float c;
}x;

结构体的自引用:

typedef struct
{
int data;
struct node* next;
}Node;
这样写代码不行,匿名结构体不要自引用
比较好的自引用方式:
typedef struct node
{
int data;
struct node* next;
}Node;
先用结构体类型,Node命名在后面

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

struct point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct point p2;//定义结构体变量p2
//初始化:定义变量的同时赋初值
struct point p3={x,y};
struct Stu //类型声明
{
char name[15];//名字
int age;//年龄
};
struct Stu s={“pan long”,22};//初始化
结构体嵌套初始化:
struct Node
{
int data;
struct point;
struct Node* next;
}n1={22,{4,5},NULL};
struct Node n2={22,{6,7},NULL};//结构体嵌套初始化

1.2结构体内存对齐

结构体大小:

#include <stdio.h>
struct s1
{
    char c1;//1
    int i;//4
    char c2;//1
};
struct s2
{
    double d;//8
    char c;//1
    int i;//4
};
//结构体嵌套问题
struct s3
{
    char a;//1
    struct s2 S2;//16
    double d;//8
};
int main()
{
    printf("%d\n", sizeof(struct s1));//打印12
    printf("%d\n", sizeof(struct s2));//打印16
    printf("%d\n", sizeof(struct s3));//打印32
    return 0;
}

上面的现象分析:我们发现结构体成员不是按照顺序在内存中连续存放的,有一定的对齐规则
结构体内存对齐的规则:
1.结构体的第一个成员永远放在相较于结构体变量起始位置的偏移量为0的位置。
2.从第二个成员开始,往后的每个成员都要对齐到某个对齐数的整数倍处。
对齐数:结构体成员自身的大小和默认对齐数的较小值。
VS上默认对齐数是8
gcc 没有默认对齐数,对齐数是结构体成员的自身大小
3.结构体的总大小,必须是最大对齐数的整数倍。
最大对齐数是:所以成员的对齐数中最大的值。
为什么存在内存对齐?

1.平台原因:不是所以的硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定的类型的数据,否则就会硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因是:为了访问未对齐的内容,处理器需要做两次内存访问;而对齐的内存访问仅需一次访问。
总结:结构体的内存对齐是拿空间来换取时间的做法。

怎么修改默认对齐数?

#pragma是预处理命令,我们使用它可以改变默认对齐数。
如:#pragma pack(8)//设置默认对齐数为8
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
结论:结构体在对齐方式不合适的时候,我们可以自己改默认对齐数。

结构体传参:
有两种方式:

//定义一个结构体
struct S
{
    int data[100];
    int num;
};
struct S s = { {1,2,3,4},1000 };
void printf1(struct S s)
{
    printf("%d\n", s.num);
}
void printf2(  struct S* ps)
{
    printf("%d\n", ps->num);
}
int main()
{
    printf1(s);//值传参
    printf2(&s);//地址传参
    return 0;
}

地址传参更好
原因:
函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。如果传一个结构体对象,结构体够大,参数压栈的时候开销比较大,所以会导致性能的下降。
结论:结构体传参的时候,要传结构体的地址。

1.3位段(位域)

位段和结构体的声明类似,有两种不同:

  1. 位段的成员必须是int 、unsigned int、或者 signed int。
  2. 位段的成员名后边有一个冒号和一个数字
    如:
    A就是一个位段类型
#include <stdio.h>
struct A
{
//占的是二进制位
    int _a : 2;
    int _b : 5;
    int _c : 10;
    int _d : 30;
};
int main()
{
    printf("%d\n",sizeof(struct A));//打印结果为8
}

位段的内存分配:
位段的成员可以是int 、unsigned int、signed int或者是char(属于整型家族)的类型。
位段在空间上是按照需要以4个字节和1个字节方式一次性去开辟得。
位段涉及很多不确定得因素,位段是不跨平台的,
例子:

#include <stdio.h>
struct S
{
    char a : 3;
    char b : 4;
    char c : 5;
    char d : 4;
};
int main()
{
    struct S s = { 0 };
    s.a = 10;
    s.b = 12;
    s.c = 3;
    s.d = 4;
    return 0;
}

空间是如何开辟得?
C语言——自定义类型详解[结构体][枚举][联合体],C语言,c语言,算法,开发语言
位段跨平台问题:

1、int 位段被当成有符号数还是无符号数是不确定的。
2、位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题)
3、位段中的成员在内存中从左向右分配,还是从右向左分配标志尚未定义。
4、当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不明确的。
结论:
跟结构相比,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。

二、枚举

2.1枚举类型的定义

枚举就是列举的意思,把可能的取值一一列举。
如:一个星期有7天,它是有限得,那么我们就可以一一列举。
一年有12个月,它是有限得,那么我们可以一一列举。

enum Day //星期
{
Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
enum Sex //性别
{
Male,Female,Secret
};
以上都是枚举类型
{}中的内容是枚举类型的可能取值,也叫做枚举常量.
这些可能取值都是有值的,默认从0开始,依次递增1,在声明枚举类型的时候也可以赋初值。

2.2枚举类型的优点

枚举类型的优点:

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

2.3枚举的使用

#include <stdio.h>
enum color
{
    red = 1,
    green = 2,
    blue = 4
};
int main()
{
    enum color  s= red;
   // s = 3;//在c++里无法从int型转换为枚举类型
    printf("%d\n", s);
    return 0;
}

三、联合体

3.1联合体类型的定义

联合体是一种特殊的自定义类型。
这种类型定义的变量也包含一系列的成员,特征是这些成员共用一块空间(所以也叫共用体)

#include <stdio.h>
//联合体类型声明
union un
{
    char c;
    int i;
};
int main()
{
    union un s;//联合体变量的定义
    printf("%d\n", sizeof( s));//计算共用体变量的大小,打印结果为5
    return 0;
}

3.2联合体的特点

联合体的成员是共用同一块内存空间,联合体变量的大小,至少是最大成员的大小(联合体至少能保存最大的那个成员)
例子:

#include <stdio.h>
union S
{
    char a;
    int i;
}s = {0};
int main()
{
    s.i = 1;
    printf("%d\n", s.a);//打印1,说明是小端
    s.i = 0x11223344;//小端存储,低字节内容存到低地址中
    s.a = 0x55;
    printf("%x\n", s.i);//打印0x11223355
    return 0;
}

3.3联合体大小的计算

联合的大小至少是最大成员的大小
当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。
#include <stdio.h>
union S
{
char a[5];//5
int i;//4
} s;
int main()
{
//共用体占多少内存空间
printf(“%d\n”, sizeof(s));//打印结果为8
return 0;
}

1、最大成员是5个字节。
2、最大成员不是最大对齐数的整数倍4(char为1,int为4),让他变成整数倍,所以打印结果为8.文章来源地址https://www.toymoban.com/news/detail-649676.html

到了这里,关于C语言——自定义类型详解[结构体][枚举][联合体]的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】自定义类型——枚举、联合体

    对枚举、联合体进行介绍,包括枚举的声明、枚举的优点,联合体的声明、联合体的大小。                  ✨  猪巴戒 :个人主页✨                 所属专栏 :《C语言进阶》         🎈 跟着猪巴戒 ,一起学习C语言🎈 目录 引言 枚举 枚举的优点 联合(共用体

    2024年02月04日
    浏览(45)
  • c语言->自定义类型联合体和枚举类型

    文章目录 ✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:橘橙黄又青_C语言,函数,指针-CSDN博客 目的:学习联合体和枚举类型的声明联合体的特点和大小,枚举类型的有点和使用。 像结构体⼀样,联合体也是由⼀个或者多个成员构

    2024年02月05日
    浏览(35)
  • 【C语言】自定义类型的详细讲解2(枚举类型、联合体类型)

    目录 1.枚举 1.1枚举优点 2.联合(共用体) 2.1联合体的应用 2.2联合体的存放 上一篇文章与大家分享并深度讨论研究了自定义类型中结构体和位段的内容,那么今天继续研究枚举和联合体的内容,希望对你有所帮助 枚举类型顾名思义就是一一列举。 把可能的取值一一列举出来

    2023年04月18日
    浏览(43)
  • 自定义类型——枚举与联合体

    枚举顾名思义就是一一列举 把可能的取值一一列举 以上定义的 enum Day , enum Sex 都是枚举类型  { }中的内容是枚举类型的可能取值,也叫 枚举常量 这些可能取值都是有值的,默认从0开始,一次递增1 当然在定义的时候也可以赋初值 例如: 我们可以使用 #define 定义常量,为

    2023年04月19日
    浏览(37)
  • 自定义类型之枚举类型(enum)和联合体类型(union)

    目录   枚举类型(enum) 什么是枚举类型? 枚举类型的使用 枚举类型的优势 枚举类型的应用场景 总结 联合体类型(union) 什么是联合体? 联合体的应用场景 联合体的注意事项 总结 枚举类型是C语言中一种非常有用的数据类型,它允许程序员定义一组命名的常量。枚举类型

    2024年02月20日
    浏览(45)
  • C语言枚举与联合体详解

        本篇文章带来 枚举与联合体 相关知识详细讲解! 如果您觉得文章不错,期待你的一键三连哦,你的鼓励是我创作的动力之源,让我们一起加油,一起奔跑,让我们顶峰相见!!! 目录 一.枚举 1.什么是枚举? 2.枚举类型的定义 3.枚举的优点 4.枚举的使用 二.联合体(共

    2024年02月15日
    浏览(43)
  • 【C语言】位段,枚举和联合体详解

      目录 1.位段 1.1 什么是位段 1.2 位段的内存分配 1.3 位段的跨平台问题 2.枚举 2.1 枚举类型的定义 2.2 枚举的优点 3. 联合(共用体) 3.1 联合类型的定义 3.2 联合的特点 3.3 联合大小的计算 位段的声明和结构体是类似的,有两个不同: 1.位段的成员必须是 int、unsigned int 或 sig

    2024年02月11日
    浏览(38)
  • C语言中的“三体”大佬们知道是什么吗? —— 结构体、枚举、联合体

    目录 前言 结构体 基本概念 结构体类型的声明 结构的声明 特殊的声明 结构的自引用 结构体变量的定义和初始化 结构体的对齐规则: 为什么要内存对齐 修改默认对齐数 修改默认对齐数的预处理命令 实际例子 结构体传参 结构体实现位段(位段的填充) 位段 什么是位段 位

    2024年02月12日
    浏览(65)
  • 【C语言】一篇文章深入解析联合体和枚举且和结构体的区别

    联合体( union )是允许一个变量通过不同的接口访问内存的一种数据类型,表示一个变量可以存储不同类型的值,而枚举是使用 enum 定义一组相关且互斥的整形常量集合。本章阿森将和你学习联合体类型的声明,特点,有关大小的计算,还有枚举类型的声明,优点和使

    2024年02月03日
    浏览(51)
  • 【C语言】联合体和枚举

    前言 这篇博客就把剩下的两个自定义类型联合体和枚举好好总结一下,让我们好好看看联合体和枚举到底是什么 个人主页:小张同学zkf 若有问题 评论区见 感兴趣就关注一下吧 目录  1. 联合体 1.1 联合体类型的声明  1.2 联合体的特点  1.3 相同成员的结构体和联合体对比  

    2024年04月14日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包