C语言--结构体(类型设计)

目录

一、基础知识

1.1 概念:

1.2 语法格式

①声明:

② 声明结构体变量

③ 初始化结构体变量

④ 结构体变量成员的使用

1.3 结构体的嵌套

二、结构体变量的大小

2.1 概念

2.2 计算

三、指针和结构体

3.1 指针变量指向结构体

3.1.1 利用指针变量访问结构体变量中的成员

3.1.2 取结构体变量中的成员的地址

3.2 结构体内有指针变量作为成员

3.3 结构体变量充当函数参数 

 3.4 结构体指针充当函数参数

 四、结构体数组

4.1 概念

4.2 语法

①声明

②初始化

五、共同体(联合体)

5.1 概念

5.2 语法

六、枚举

6.1 概念

6.2 语法

①声明枚举类型

②定义变量


一、基础知识

1.1 概念:

描述一个复杂的数据类型,该类型 struct 需要若干个不同的数据类型的变量组成。(由程序开发者自己设计的类型)

例如:学生

姓名,学号,年龄,性别这些内容都是不同数据类型的。我们无法使用数组或其他基本数据类型来

描述,因此我们需要一个复合如下要求的变量

①变量能够存储多个数值

②数值的数据类型不同

③这些数值共同组成了一个整体用于描述同一种事物

C语言提供了一种复合数据类型来保存这种数据—结构体类型,用户可以自行定义其中的内容用来

描述一个全新的类型。

1.2 语法格式

①声明:

struct 结构体类型名

{

   数据类型 变量名;(结构体成员)

   ……

};

struct Stu
{
	char _name[100];
	int id;
	int age;
	char sex;
};
② 声明结构体变量

struct 结构体类型名  结构体变量名;

	//变量声明
	struct Stu s1;
③ 初始化结构体变量

struct 结构体类型名  结构体变量名={值1,值2,。。。值n};

//初始化
struct Stu s2 = { "小强", 1, 21, 'F' };
struct Stu s3 = { "丧彪", 2 };
s3.age = 19;
s3.sex = 'M';
printf("我叫%s,我的学号是%d,我今年%d岁了,我的性别是%c\n", s3._name, s3.id, s3.age, s3.sex);
	
④ 结构体变量成员的使用

结构体变量名.成员名

1.3 结构体的嵌套

结构体变量可以嵌套定义

struct A

{

  成员;

};

struct B

{

   struct A 变量;

};

struct Date
{
	int year;
	int month;
	int day;
};
struct Phone
{
	char _name[50];
	int price;
	struct Date date;
};

二、结构体变量的大小

2.1 概念

个结构体变量的大小是由以下两个条件共同决定的:

①结构体内部的成员变量的大小

②字节对齐规则 :

        内存大小的基本单位是字节(byte),理论上来讲,可以从任意地址访问变量,但是实际上

CPU并非逐字节读写内存,而是以2、4、或8的倍数的字节块来读写内存,因此就会对基本数据类

型的地址做出一些限制。即它的地址,必须是2、4、或8的倍数。那么就要求各种数据类型按照一

定的规则在空间上排列,这就是对齐。

2.2 计算

以结构体内部最大元素的所占内存的大小作为内存的基本分配单元,一个结构体的大小是这个结构

体中最大元素的内存单元的整数倍;结构体变量的存储是有条件的“连续存储”。因为每次分配的内

存大小都是最大成员变量内存大小的整数倍所以在其中是有“空洞”空间的。

     

所占内存大小:8字节

所占内存大小:8字节

所占内存大小:16字节,原因:结构体变量的存储是有条件的“连续存储”。因为每次分配的内存大

小都是最大成员变量内存大小的整数倍所以在其中是有“空洞”空间的。

本来按分配原则:double的3倍,24字节,但是因为存储是连续的,给第一个x分配8个字节,它本

身占4个,有4个空洞,又因为存储连续,下一个字节继续放c,共用所分配的8字节。

嵌套结构体类型,所占内存:

所占内存:24 byte ,Stu中最大的数据类型所占8字节,以其作为基类型*3

给数据,看下具体内存中是怎么存储的:

三、指针和结构体

3.1 指针变量指向结构体

需要创建一个基类型是结构体类型的指针变量

结构体的地址就是结构体中第一个成员的首字节地址。

3.1.1 利用指针变量访问结构体变量中的成员

语法:指针变量名->结构体成员名

利用指针变量加*来当做变量本身,需要将*和指针变量利用括号括起来,否则,指针变量首先会和.

运算先结合。

(*指针变量名).成员

两种访问方式都可以访问到结构体中的a变量的值。

3.1.2 取结构体变量中的成员的地址

&结构体变量名.成员    &info.x   &info.data.a

&结构体指针变量->成员   &p->a

#include <stdio.h>
struct DATA
{
	int a;
	char b;
	double c;
};
struct Info
{
	int x;
	int y;
	struct DATA data;
};
int main()
{
    struct DATA data = { 12, 'A', 0.9 };
    struct DATA* p = NULL;
    p = &data;//p == &data
    printf("%d\n", sizeof(p));
    printf("%p %c %.3lf\n", &p->a, p->b, p->c);
    struct Info info = { 7, 8, { 100, 'B', 3.14 } };
    printf("%p\n", &info.x);
    printf("%p\n", &info.data.a);
}

 

3.2 结构体内有指针变量作为成员

定义一个结构体,有一个x变量,一个指针p。

#include <stdio.h>
struct Num
{
	int x;
	int* p;
};
int main()
{
	int m = 999;
	struct Num obj = { 0, &m }; // 指针p保存的是m的地址
	printf("%d %p\n", obj.x,obj.p);  // obj.p访问到的是p指针保存的地址
	printf("%d\n", *(obj.p)); //*才能访问到p指针地址上存的数值
}

3.3 结构体变量充当函数参数 

概念:形式参数是结构体变量名,意味着参数在传递时,由实际参数(结构体变量)传递给形式参

数(结构体变量)。实际上适合普通变量的参数传递一样的。

返回值类型 函数名(struct 结构体类型名 变量名)

{


}

#include <stdio.h>
struct Stu
{
	char _name[50];
	int id;
};
void Fun(struct Stu s){
	printf("注意看这个女人叫%s,她的id是%d\n", s._name, s.id);
}
int main()
{
	struct Stu student = { "小美", 1 };
	Fun(student);
	printf("注意看这个女人叫%s,她的id是%d\n", student._name, student.id);
	return 0;
}

 3.4 结构体指针充当函数参数

概念:形式参数是指向结构体变量的指针,意味着在参数传递时,由实际参数(结构体变量地址

Fun1(&student);  传递给形式参数(结构体指针变量 struct Stu* pStu )。本质上就是地址传递过

程。

#include <stdio.h>
struct Stu
{
	char _name[50];
	int id;
};
void Fun1(struct Stu* pStu){
	//pStu->id = 2;
	(*pStu).id = 2;
}
int main()
{
	struct Stu student = { "小美", 1 };
	Fun1(&student);
	printf("注意看这个女人叫%s,她的id是%d\n", student._name, student.id);
	return 0;
}

结构体指针变量接收结构体变量的地址,

 (*pStu).id = 2; 将 id 改成 2

 四、结构体数组

4.1 概念

数组的每一个元素都是一个结构体变量。

4.2 语法

①声明

struct 结构体类型名 数组名[长度];

②初始化

五、共同体(联合体)

5.1 概念

一种复合数据类型,内部的成员变量共享同一块内存,即每一个数据成员的起始地址都相同,所有

数据成员占用同一段内存。修改一个数据成员就会影响其他数据成员的值。

结构体变量占用的内存大大于等于所有数据成员占用内存的总和,涉及字节对其问题。

共同体变量占用的内存大小等于最大的数据成员占用的内存大小,共同体使用了内存覆盖技术,同

一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来的成员的值覆盖掉。

5.2 语法

union 类型名 变量名;

#include <stdio.h>
union UN
{
	int x;
	char c;
};
int main()
{
    union UN obj2;
    printf("%d\n", sizeof(obj2));
}

 所占内存大小:4字节

六、枚举

6.1 概念

将所有的数字一一列举出来并命名

目的:方便用户进行识别,提升代码的阅读性和可维护性

6.2 语法

①声明枚举类型

enum 类型名{值1=常量,值2,。。。值N};

②定义变量

enum 类型名 变量名 = 值

默认情况下枚举变量的值是从0开始的,且在赋值和使用时,只能使用枚举类型中出现的值

注:枚举类型没有++ --运算

#include<stdio.h>
enum week { Mon, Tues, Wed, Thurs = 100, Fri, Sat, Sun };

double Div(int x, int y)
{
	if (y != 0)
	{
		printf("%lf\n", (double)x / y);
		return OK;
	}
	else
	{
		return ERROR;
	}
}

int main()
{
	enum week weekday = Fri;
	printf("%d\n", sizeof(weekday));
	printf("%d\n", weekday);
}

枚举变量的大小,实质是常数所占内存空间的大小,上图代码,内存大小:4字节,运行结果如下

其中,枚举类型,第一个表示0,所以 Mon:0,Tues:1,Wed:2,其中Thurs = 100,后续的值依次+1,所以,Fri:101。

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值