(八)C语言之结构

今天来说一下C语言里的结构体(struct)、共用体(l联合体)union、枚举。

(一)结构体:struct

1.1 概念

  • 是一种自定义的数据类型
  • 结构体是构造类型的一种
  • 不同数据类型的集合
  • 地址空间连续,每次分配最大数据类型的宽度
  • 占用内存为所有变量的总大小(注意字节对齐问题)

1.2 定义

1.先定义结构体类型,再说明结构体变量

struct stu
{char *name;  //姓名int num;  //学号int age;  //年龄float score;  //成绩
};
struct stu  student;

上面的程序使用strcuct关键字定义了一个结构体名为stu的结构体类型。和定义变量一样,声明一个结构体类型变量可以使用:数据类型 变量名 的形式。
struct stu student表示定义了一个变量名为stduent,类型为stu的结构体。该结构体含有4个成员:name、num、age、score
注意大括号后面的分号;不能少,这是一条完整的语句。
2.定义结构体类型的同时定义结构体变量

struct stu
{char *name;  //姓名int num;  //学号int age;  //年龄float score;  //成绩
}student;

在定义时直接声明结构体变量,只需要将结构体变量名放在花括号后面,并加上分号即可。
3.直接说明结构体变量

struct 
{char *name;  //姓名int num;  //学号int age;  //年龄float score;  //成绩
} student;

这种定义方式并不常用,这样做书写虽然简单,但是因为没有结构体名,后面就没法用该结构体定义新的变量。
4.typedef重定义

typedef struct 
{char *name;  //姓名int num;  //学号int age;  //年龄float score;  //成绩
} STU;
STU student;

这种方式比较常见,我们使用typedef重定义结构体为STU,这里STU就是此结构体类型,可以用STU去定义结构体变量

1.3 初始化

1.在定义结构体变量的时候全部初始化

struct stu
{char *name;  //姓名int num;  //学号int age;  //年龄float score;  //成绩
}student={“ha”,1234,56,99};

2.定义完结构体变量后,之后只能单个赋值

struct stu
{char *name;  //姓名int num;  //学号int age;  //年龄float score;  //成绩
};
struct stu  student;
student.name="ha";
student.num=1234;
student.age=56;
student.score=99;

1.4 调用

结构体变量.成员

结构体变量名+点(’.’)+成员就可以调用了

1.5 结构体指针

当一个指针变量指向结构体时,我们就称它为结构体指针。C语言结构体指针的定义形式一般为:

struct 结构体名 *变量名;
//结构体
struct stu{char *name;  //姓名int num;  //学号int age;  //年龄float score;  //成绩
} stu1 = { "hah", 12, 18, 23, 136.5 };
//结构体指针
struct stu *pstu = &stu1;

注意结构体变量名和数组名不同,数组名在表达式中会被转换为数组指针,而结构体变量名不会,无论在任何表达式中它表示的都是整个集合本身,要想取得结构体变量的地址,必须在前面加&,所以给 pstu 赋值只能写作:

1.6 获取结构体成员

通过结构体指针可以获取结构体成员,一般形式为:

(*pointer).memberName

或者:

pointer->memberName

第一种写法中,.的优先级高于*,(pointer)两边的括号不能少。如果去掉括号写作pointer.memberName,那么就等效于*(pointer.memberName),这样意义就完全不对了。

第二种写法中,->是一个新的运算符,习惯称它为“箭头”,有了它,可以通过结构体指针直接取得结构体成员;这也是->在C语言中的唯一用途。

1.7 结构体内存分析

注意点

  1. 给整个结构体变量分配储存空间和数组一样,从内存地址比较大的开始分配
  2. 给结构体变量中的属性分配储存空间也和数组一样,从所占内存地址比较小的开始分配
  3. 定义结构体类型不会分配储存空间,只有定义结构体变量的时候才会分配储存空间
  • 结构体在分配内存的时候,会做一个内存对齐的操作
  • 会先获取所有属性中占用内存最大的属性的字节数
  • 然后在开辟出最大属性字节的内存给第一个属性,如果分配给第一个属性之后还能继续分配给第二个属性,那么就继续分配给第二个属性
  • 如果分配给第一个属性之后,剩余的内存不够分配给第二个属性了,那么会再次开辟最大属性的内存,再次分配 依次类推
#include <stdio.h>int main(){//定义结构体struct Person{char name; // 1 个节点  //开辟4个字节 char 占用1个int age;  // 4个字节   // 剩余三个 不够int  再开辟4个字节int money; // 4个字节 // 再开辟4个字节};struct Person p; // 所以p = 4+4+4printf("sizeof(p) = %i\n",sizeof(p)); // 12个字节return 0;
}

(二)共用体(联合体):union

2.1概念

  • 所有变量共用一段空间
  • 每次分配按最大长度进行分配
  • 是一种构造数据类型
  • 同一时刻只能保存一个成员的值
  • 不能直接引用共用体变量名

2.2定义

它的定义和结构体一样,分为先定义共用体再说明共用体变量、在定义共用体的同时说明共用体变量、直接说明共用体变量

union 共用体名{成员列表
};

示例:

//先定义共用体再说明共用体变量
union data{int n;char ch;double f;
};
union data a, b, c;

2.3 引用

和结构体一样,通过共用体变量名 . 成员名

union data{int n;char ch;double f;
} a, b, c;
a.n=3;

关于共用体的详细介绍可以看下这篇文章C语言共用体(C语言union用法)详解,讲到共用体这里要说明一下大小端模式的问题。
大小端
小端模式:低地址存放低字节,高地址存放高字节
大端模式:低地址存放高字节,高地址存放低字节

(三)枚举:enum

3.1 概念

  • 作用:列举出所有的可能性,增强代码的可阅读性
  • 枚举成员都是常量
  • 不能再对已经定义好的枚举常量赋值

3.1 定义

enum 枚举名 
{
枚举变量
};

示例:

enum week
{ 
Mon, Tues, Wed, Thurs, Fri, Sat, Sun};
typedef enum
{
Mon, Tues, Wed, Thurs, Fri, Sat, Sun
}Date;

枚举是一种类型,通过它可以定义枚举变量:

Date a,b,c

我们也可以给每个名字都指定一个值:

enum week{ Mon = 1, Tues = 2, Wed = 3, Thurs = 4, Fri = 5, Sat = 6, Sun = 7 };

更为简单的方法是只给第一个名字指定值:

enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun };

这样枚举值就从 1 开始递增,跟上面的写法是等效的。
也可以在定义枚举类型的同时定义变量:

enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } a, b, c;

有了枚举变量,就可以把列表中的值赋给它:

enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun };
enum week a = Mon, b = Wed, c = Sat;

或者:

enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } a = Mon, b = Wed, c = Sat;

特点:可以在定义枚举时给成员赋值,被赋值的成员往后依次增加1,也可以在中间改变某一个成员的值。

3.1 引用

直接使用就行,需要注意的是**枚举列表中的数据作用范围是全局的,不能在定义与它们名字相同的白能量;Mon、Tues、Wed 等都是常量,不能对它们赋值,只能将它们的值赋给其他的变量。
示例:

#include <stdio.h>
int main(){enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } day;scanf("%d", &day);switch(day){case 1: puts("Monday"); break;case 2: puts("Tuesday"); break;case 3: puts("Wednesday"); break;case 4: puts("Thursday"); break;case 5: puts("Friday"); break;case 6: puts("Saturday"); break;case 7: puts("Sunday"); break;default: puts("Error!");}return 0;
}

Mon、Tues、Wed 这些名字都被替换成了对应的数字。这意味着,Mon、Tues、Wed 等都不是变量,它们不占用数据区(常量区、全局数据区、栈区和堆区)的内存,而是直接被编译到命令里面,放到代码区,所以不能用&取得它们的地址。这就是枚举的本质。


本文章仅供学习交流用禁止用作商业用途,文中内容来水枂编辑,如需转载请告知,谢谢合作

微信公众号:zhjj0729

微博:文艺to青年

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531448.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

插入排序之表插入排序

1.表插入排序只是求得一个有序的链表&#xff0c;它是修改指针的值来代替移动记录&#xff0c;操作过程如下 2.但是这样只能进行顺序查找&#xff0c;不能进行随机查找&#xff0c;为了能实现有序表的折半查找&#xff0c;需要对记录进行重新排列。操作过程如下&#xff1a; 3.…

电容降压LED驱动电路

电容降压电路具有体积小、成本低、电流相对稳定等优点&#xff0c;可应用于小功率的LED驱动电路中&#xff0c;本文主要介绍了电容降压电路的基本电路 图一&#xff1a; 电容降压式简易电源的基本原理如图一所示&#xff0c;C3为降压电容器&#xff1b;D4为半波整流二极管&…

延时电路分析

延时电路经常会用到&#xff0c;RC电路是比较简单的电路。在电路设计中经常会用到将电阻和电容正极连接&#xff0c;电阻另一端接上电源&#xff0c;电容负极接地。 简单的延时电路 上面就是延时的电路图了&#xff0c;延时的时间为T-ln((VCC-Vout)/VCC)RC&#xff0c;公式中的…

恒流电路的分析(一)

在这里分析一个简单的LED恒流电路&#xff0c;软件采用Multisim进行波形采集 一、元器件 R1为80KΩ左右的金属膜电阻&#xff1b;Q选取耐压值超过350V的VPN三极管&#xff1b;D选取2V左右的稳压二极管(如1N4680)&#xff1b;C2选取10V、100UF以上的电解电容&#xff1b;R2选择…

ST-LINK USB communication error解决方法

今天在用stlink-v2下载程序时出现ST-LINK USB communication error&#xff0c;突然就出现了这个问题&#xff0c;在网上找了好多解决办法都不可以用&#xff0c;下面给出我的解决方案&#xff0c;文章末尾给出了网上的几种解决办法&#xff0c;仅供参考。 第一步&#xff1a;找…

利用STM32制作红外测温仪之硬件设计

最近受疫情的影响详细大家都在家里没事干&#xff0c;这里利用stm32最小系统做一个红外测温仪 这篇教程里我们来制作红外测温仪需要用到的硬件&#xff0c;关于PCB的工程文件&#xff0c;后文会给出。 &#xff08;一&#xff09;系统分析 由于我们的功能比较单一&#xff0c;…

如何在博客中插入背景音乐

1.首先进入网音乐官方网站&#xff1b; 2.查找自己喜欢的歌&#xff0c;看到如下界面 3.点击"生成外链播放器" 4.看到下面的html代码了吗&#xff1f;将代码进行复制。 5.进入博客园&#xff0c;点击 "管理" ->"设置"&#xff0c; 将代码复制…

常用存储器介绍

注意&#xff1a;"易失/非易失"是指存储器断电后&#xff0c;它存储的数据内容是否会丢失的特性。 &#xff08;一&#xff09;RAM和ROM 1.1 RAM RAM即随机存储器&#xff0c;它是指存储器中的数据被读入或者写入与信息所在位置无关&#xff0c;时间都是相同的 1…

TortoiseGit与github实现项目的上传

1. 下载并安装相关软件 这里主要涉及的软件包括msysgit和TortoiseGit。 msysgit的下载地址&#xff1a;http://msysgit.googlecode.com/files/Git-1.7.4-preview20110204.exe TortoiseGit的下载地址&#xff1a;http://code.google.com/p/tortoisegit/downloads/list&#xff0…

uboot启动流程分析

Uboot的启动流程分为两个阶段&#xff0c;第一阶段主要是汇编语言编写&#xff0c;第二阶段是C语言编写&#xff0c;每个阶段所做的工作不同&#xff0c;这篇文章分析的是uboot 2010版&#xff0c;以tiny4412的uboot为例。 启动过程涉及的主要文件&#xff1a; arch/arm/cpu/a…

(二)linux内核镜像制作

&#xff08;一&#xff09;目的 在进行嵌入式开发的时候&#xff0c;我们往往会先在电脑上安装交叉编译器&#xff0c;然后编译目标板上的代码&#xff0c;最后把代码下载到电路板中&#xff0c;嵌入式系统组成包括&#xff1a;BootLoaderkernelfilesystemapplication&#x…

js+css实现骰子的随机转动

网上找的例子&#xff0c;然后增添了新的东西&#xff0c;在这里展示一下...... 效果图预览&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html x…

linux的mount和umount指令使用

mount即挂在操作&#xff0c;磁盘或分区创建好文件系统后需要挂载到一个目录&#xff08;一般mount在/mnt下&#xff09;才能使 用&#xff0c;和winsdows不同的是在linux下需要手动挂载。 用法&#xff1a;mount [-t文件系统] [选项] 设备目录注意&#xff1a;[ ]为可选项…

斐波那契的四种求法

首先看一下斐波那契的矩阵表示&#xff1a; 数列的递推公式为&#xff1a;f(1)1&#xff0c;f(2)2&#xff0c;f(n)f(n-1)f(n-2)(n>3) 用矩阵表示为&#xff1a; 进一步&#xff0c;可以得出直接推导公式&#xff1a; #include<iostream> #include<cstring> #i…

利用STM32制作红外测温仪之软件设计(MLX90614)

目录&#xff08;一&#xff09;工程目录如图&#xff1a;&#xff08;二&#xff09;main函数实现&#xff1a;&#xff08;三&#xff09;MLX90614测温代码实现前面介绍了使用 STM32制作红外测温仪硬件设计,今天来说一下软件的实现&#xff0c;具体的程序&#xff0c;完整的k…

Windows下使用Dev-C++开发基于pthread.h的多线程程序

一、下载Windows版本的pthread 目前最新版本是&#xff1a;pthreads-w32-2-9-1-release.zip。 二、解压pthread到指定目录 我选择的目录是&#xff1a;E:\DEV-CPP\Pthread完成后&#xff0c;该目录会多出三个文件夹&#xff1a;Pre-built.2&#xff0c;pthreads.2&#xff0c;Q…

(三)linux之根文件系统的制作

&#xff08;一&#xff09;准备工作 Ubuntu 16.04系统linux-3.5内核:linux-3.5-20190929交叉编译工具arm-linux-gcc-4.5.1-v6-vfp-20120301.rarbusybox源码包&#xff1a;busybox-1.21.1.rar &#xff08;二&#xff09;工具介绍 &#xff08;1&#xff09;交叉编译器 这个…

(四)Linux内核模块化编程

目录&#xff08;一&#xff09;模块化编程简介&#xff08;二&#xff09;安装卸载模块命令.&#xff08;三&#xff09;将自定义功能添加到内核三种方法&#xff08;1&#xff09;修改Kconfig和Makefile&#xff08;2&#xff09;直接修改功能对应目录下的Makefile文件&#…

基于X86平台的PC机通过网络发送一个int(32位)整数的字节顺序

1.字节顺序  字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序&#xff0c;通常有小端、大端两种字节顺序。小端字节序指低字节数据存放在内存低地址处&#xff0c;高字节数据存放在内存高地址处&#xff1b;大端字节序是高字节数据存放在低地址处&#xff0c;低字…

codeforces Round #320 (Div. 2) C. A Problem about Polyline(数学) D. Or Game(暴力,数学)

解题思路&#xff1a;就是求数 n 对应的二进制数中有多少个 1 #include <iostream> #include<cstdio> using namespace std; int main(){int n;cin>>n;int ans 0; // while(n){//这也是一种好的方法 // n n&(n-1); // ans; // }while(n…