【C语言】自定义类型:结构体【结构体内存具详细】,枚举,联合

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

 【C语言】自定义类型:结构体【结构体内存具详细】,枚举,联合,【C语言】,c语言,开发语言

目录

一、结构体

1.结构的声明

 2.特殊的声明

3.结构的自引用

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

 5.结构体内存对齐(重点来了)

6.为什么会存在内存对齐 

7.修改默认对齐数

8.结构体传参

二、位段

1.什么是位段

2.位段的内存分配

3.位段的跨平台问题

三、枚举

1.枚举类型的定义

2.枚举的优点

3.枚举的使用

四、联合(共用体)


一、结构体

在此之前简单地介绍了结构体的使用初阶结构体

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

1.结构的声明

//结构体的声明
struct tag 
{
	member - list;//成员列表
}variable-list;//变量列表

【例如】

struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char id[20];
};

 2.特殊的声明

在声明结构体的时候,可以不完全的声明。

如 匿名结构体类型

//匿名结构体类型
struct 
{
	int a;
	char b;
	float c;
}x;
struct 
{
	int a;
	char b;
	float c;
}a[20],*p;
//注意 不能这样写 p = &x;//编译器会把上述当成两个不同的结构体,所以是非法的

3.结构的自引用

就是结构体中含有一个类型为结构体本身的成员,如果学过数据结构的话,可能会知道链表中的node节点 就用到了结构体的自引用。

结构体的自引用方式

struct Node 
{
	int data;//数据域
	struct Node* next;//指针域,指向下一个节点
};
//另一种写法,使用类型重命名
typedef struct Node
{
	int data;
	struct Node* next;
}Node;//这样就可以 当写 struct Node 可以写为 Node

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

(1)声明类型的同时定义变量p1

//结构体变量的定义和初始化
struct Point
{
	int x;
	int y;
}p1;//声明类型的同时定义变量p1

(2)初始化,定义变量的同时赋值

struct Point p3 = {x,y};

struct Stu 
{
	char name[15];
	int age;
};
struct Stu s = {"zhangsan",20};

(3)结构体嵌套初始化

struct Stu 
{
	int data;
	struct Point p;
	struct Node* next;
}n1 = { 10,{4,5},NULL };//结构体嵌套初始化

 5.结构体内存对齐(重点来了)

先来个问题,如何计算结构体的大小呢?这个问题就涉及了结构体内存对齐

看下方代码,并试着计算这俩个结构体分别是多大

struct S1 
{
	char c1;
	int a;
	char c2;
};
struct S2
{
	char c1;
	char c2;
	int a;
};

如果不了解结构体内存对齐的话,可能会认为这两个结构体不一样大吗?

当我们试着打印这两个结构体的大小

【C语言】自定义类型:结构体【结构体内存具详细】,枚举,联合,【C语言】,c语言,开发语言

这时我们发现这两个结构体的大小不一样大,这是为什么呢?

看完接下来的结构体内存对齐,就明白了。

重点

要计算结构体的大小,那么我们就要掌握下方的

结构体对齐规则:

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

根据上述结构体对齐规则,我们来分析下方代码

【1】

struct S1 
{
	char c1;//所占大小为1
	int a;//所占大小为4
	char c2;//所占大小为1
};
//该结构体的总体大小为?

该图解具详细 

【C语言】自定义类型:结构体【结构体内存具详细】,枚举,联合,【C语言】,c语言,开发语言

接着来分析   struct S2

【2】

struct S2
{
	char c1;//所占大小为1
	char c2;//所占大小为1
	int a;//所占大小为4
};

//该结构体总体大小为?

图解具详细:

【C语言】自定义类型:结构体【结构体内存具详细】,枚举,联合,【C语言】,c语言,开发语言

有了上述两个 我们接着再来看两个,巩固一下结构体内存

【3】根据结构体的内存对齐计算结构体的大小

struct S3 
{
	double d;
	char c;
	int i;
};

图解具详细:

【C语言】自定义类型:结构体【结构体内存具详细】,枚举,联合,【C语言】,c语言,开发语言

【4】 计算结构体S4的大小

struct S3 
{
	double d;
	char c;
	int i;
};
struct S4 
{
	char z;
	struct S3 s3;
	double d;
};

【C语言】自定义类型:结构体【结构体内存具详细】,枚举,联合,【C语言】,c语言,开发语言

6.为什么会存在内存对齐 

简单来说就是

  1. 平台原因 某些硬件导致的原因
  2. 性能原因 访问一些内存时,在访问为未对齐的内存,可能会访问两次内存,而访问内存对齐的内存时 ,只要访问一次即可 

所以,对于结构体的内存对齐 是 通过 空间 来换取 时间 的做法

7.修改默认对齐数

我们可能之前会看到#pragma 这个预处理指令

#pragma 可以修改默认对齐数

#include<stdio.h>
#pragma pack(1)//对齐数修改为4
struct S1 
{
	char c1;
	int a;
	char c2;
};
int main() 
{
	printf("%d",sizeof(struct S1));
}

这样经过修改默认对齐数,改为1。这样计算出来的结构体大小就是6了。

有了这个pragma,当结构体对齐方式不合适的时候我们就可以修改默认对齐数,进而来调整结构体的大小。

8.结构体传参

#include<stdio.h>
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);
}
//结构体地址传参
print2(struct S* s)
{
	printf("%d\n",s->num);
}
int main() 
{
	print1(s);//传结构体
	print2(&s);//传地址
	return 0;
}

注意: 因为函数传参的时候要压栈,会有时间和空间上的系统开销。而传结构体的地址的时候与会减少系统的开销。

二、位段

1.什么是位段

位段的声明和结构体是类似的,但有两点不同

  1. 位段的成员必须是int、unsigned int 、
  2. 位段的成员名后边有一个冒号和一个数字。

【例】

struct A {
	int a : 2;
	int b : 3;
	int c : 4;
	int d : 5;
};

2.位段的内存分配

位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型

位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。

位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段

3.位段的跨平台问题

1. int 位段被当成有符号数还是无符号数是不确定的。
2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机
器会出问题。
3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是
舍弃剩余的位还是利用,这是不确定的。

三、枚举

1.枚举类型的定义

枚举就是列举

enum Color 
{
	RED,
	GREEN,
	BLUE
};
enum Sex 
{
	MALE,
	FEMALE,
	SECRET
};

enum Sex,enum Color都是枚举类型,{ }中的内容就是枚举类型可能取的值,也叫枚举常量

有些可以有值得,默认从0开始,一次递增1,定义的时候可以赋值

enum Color 
{
	RED=1,
	GREEN=2,
	BLUE=3
};

2.枚举的优点

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

3.枚举的使用

enum Color
{
	RED = 1,
	GREEN = 2,
	BLUE = 3
};
enum Color clr = GREEN;//这样不会出现类型的差异
clr = 5;

四、联合(共用体)

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

#include<stdio.h>
union Un
{
	int i;
	char c;
};
union Un un;
int main()
{
	un.i = 0x11223344;
	un.c = 0x55;
	printf("%d\n",&(un.i));
	printf("%d\n",&(un.c));
	printf("%x\n",un.i);
	return 0;
}

【C语言】自定义类型:结构体【结构体内存具详细】,枚举,联合,【C语言】,c语言,开发语言

从第三个的打印结果我们可以看出来 联合体中的成员就是共用同一块内存空间。

来一个笔试题

判断当前计算机的大小端存储

//判断大小端的存储
#include<stdio.h>
int check_sys() 
{
	int i = 1;
	return *((char*)&i);
	// 00 00 00 01 大端
	// 01 00 00 00 小端
	//地址 低---->高
}
int main() 
{
	int ret = check_sys();
	if (ret == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

上述代码就是我们通过取地址的方式来判断的

接下来我们来使用联合体来判断判断当前机器的字节序

//使用联合体来判断当前机器的字节序
#include<stdio.h>
int check_sys() 
{
	union 
	{
		int i;
		char c;
	}un;
	un.i = 1;
	return un.c;
	//这里的联合体共用是同一块内存空间
}
int main() 
{
	int ret = check_sys();
	if (ret == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

【C语言】自定义类型:结构体【结构体内存具详细】,枚举,联合,【C语言】,c语言,开发语言文章来源地址https://www.toymoban.com/news/detail-724323.html

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

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

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

相关文章

  • 【C语言】——自定义类型详解:结构体,枚举,联合

    大家好,今天为大家分享一下C语言中的那些自定义类型:结构体,枚举,联合,还有之前可能不曾了解的结构体内存对齐、位段等知识点!!! 一、结构体 结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。 结构的声明 : 例如描述一个学生

    2024年02月07日
    浏览(50)
  • 详解C语言自定义类型(结构体,枚举,联合)

    ❤️ 作者简介 :RO-BERRY 致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识,对纯音乐有独特的喜爱 📗 日后方向 : 偏向于CPP开发以及大数据方向,如果你也感兴趣的话欢迎关注博主,期待更新 🎄结构体是一些值的集合,这些值称为成员变量。结构的每个成员可以是不

    2024年02月16日
    浏览(39)
  • 【C语言进阶】自定义类型:结构体,枚举,联合

    1.1结构体类的基础知识 结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。 1.2结构的声明 例如描述一个学生: 1.3特殊的声明 在声明结构的时候,可以不完全的声明 上面的两个结构在声明的时候省略掉了结构体标签(tag) 当我们使用匿名结

    2024年02月07日
    浏览(43)
  • C语言自定义类型 — 结构体、位段、枚举、联合

    本期主要对通讯录三篇博客文章进行补充 通讯录文章:通讯录系列文章 对 结构体 进行详细介绍,其次讲解位段、枚举、联合体 在C语言中,结构是一种用户自定义的数据类型,它可以由不同类型的数据成员组成,每个数据成员可以是不同的数据类型。 结构的作用是将多个不

    2024年02月14日
    浏览(42)
  • 手撕自定义类型:结构体,枚举,联合——【C语言】

      在开始学习之前我们先来欣赏一下五岳之一华山的风景,来营造一个好心情,只有一个好心情我们才能更好的学习 目录 结构体 1 结构体的声明 1.1 结构的基础知识 1.2 结构的声明 1.3 特殊的声明 1.4 结构的自引用 1.5 结构体变量的定义和初始化  1.6 结构体内存对齐(重点)

    2024年02月16日
    浏览(46)
  • 【C语言进阶】自定义类型之结构体,枚举和联合

    人一能之,己百之;人十能之,己千之。                             ——《中庸》   目录 一.结构体 1.结构的基础知识 2.结构体的声明 3.结构体成员的类型 4.结构体变量的定义和初始化: 5.结构体成员的访问: 6.结构体传参  7.结构体内存对齐:结构体的大小 8.为什么要

    2023年04月23日
    浏览(43)
  • C语言——自定义类型详解[结构体][枚举][联合体]

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

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

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

    2023年04月18日
    浏览(42)
  • 【再识C进阶4】详细介绍自定义类型——结构体、枚举和联合

           在上一篇博客中,我们已经详细地学习了字符分类函数、字符转换函数和内存函数。那这一篇博客和上一篇博客的关系不是那么相连。        这一篇博客主要介绍一下 自定义类型 ,因为在解决实际问题时, 由于世界上的因素有很多,我们需要建立不同的数据

    2024年02月08日
    浏览(49)
  • 一篇博客学会系列(2)—— C语言中的自定义类型 :结构体、位段、枚举、联合体

    目录  前言 1、结构体 1.1、结构体类型的声明 1.2、特殊的结构体类型声明 1.3、结构体的自引用 1.4、结构体的定义和初始化 1.5、结构体成员变量的调用 1.6、结构体内存对齐  1.6.1、offsetof 1.6.2、结构体大小的计算 1.6.3、为什么存在内存对齐?  1.7、 修改默认对齐数 1.8、结构

    2024年02月08日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包