015 C语言基础:C结构体、共用体

一:C语言结构体

1.1:概述

前面的章节学习了数组,他是一组具有相同类型的数据的集合。但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放。

在C语言中,可以使用结构体来存放一组不同类型的数据。结构体的定义形式为:

struct 结构体名{
	结构体所包含的变量或数组
};

结构体是一种集合,里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称之为结构体的成员。

struct stu{
	char *name;		// 姓名
	int num;		// 学号
	int age;		// 年龄
	char group;		// 所在学习小组
	float score;	// 成绩
};

注意大括号后面的分号;不能少,这是一条完整的语句。

像int、float、char等是由C语言本身提供的数据类型,不能再进行分拆,我们称之为基本数据类型;而结构体可以包含多个基本类型的数据,也可以包含其他的结构体,我们将它称为复杂数据类型或构造数据类型。

1.2:结构体变量

既然结构体是一种数据类型,那么就可以用它来定义变量。例如;

struct stu stu1, stu2;

定义了两个变量 stu1 和 stu2,它们都是 stu 类型,都由 5 个成员组成。注意关键字struct不能少。

struct stu{
	char *name;  //姓名
	int num;  //学号
	int age;  //年龄
	char group;  //所在学习小组
	float score;  //成绩
} stu1, stu2;

1.3:成员的获取与赋值

结构体和数组类似,也是一组数据的集合,整体使用没有太大的意义。数组使用下标[]获取单个元素,结构体使用点号.获取单个成员。

格式为:结构体变量名.成员名;

实例:
	#include <stdio.h>
	int main(){
		struct{
			char *name;
			int num;
			int age;
			char group;
			float score;
		}stu1;

		// 给结构体成员赋值
		stu1.name = "tom";
		stu1.num = 12;
		stu1.age = 22;
		stu1.group = 'A';
		stu1.score = 123.5;

		// 读取结构体成员的值
		printf("%s 的学号是:%d, 年龄是 %d, 在%c组, 今年的成绩是%.1f \n", stu1.name, stu1.num, stu1.age, stu1.group,stu1.score);
	}
结果:
	┌──(root💀kali)-[~/Desktop/c_test]
	└─# ./jiegoutichengyuan 
	tom 的学号是:12, 年龄是 22, 在A组, 今年的成绩是123.5 
除了可以对成员进行逐一赋值,也可以在定义的时候整体赋值,例如;
	struct{
		char *name;
		int num;
		int age;
		char group;
		float score;
	} stu1, stu2 = {"tom", 12, 22, 'A', 123.5};

需要注意的是,结构体是一种自定义的数据类型,是创建变量的模板,不占用内存空间;结构体变量才包含了实实在在的数据,需要内存空间来存储。

 

二:C语言结构体数组

所谓结构体数组,是指数组中的每个元素都是一个结构体。在实际应用中,结构体数组常被用来表示一个拥有相同数据结构的群体,比如一个班的学生,一个车间的职工等。

实例:
	struct stu{
		char *name;     // 姓名
		int num;        // 学号
		int age;        // 年龄
		char group;     // 所在小组
		float score;    // 成绩
	}class[5];          // 表示一个班级有5个学生
结构体数组在定义的同时也可以初始化,例如;
	#include <stdio.h>
	struct stu{
		char *name;     // 姓名
		int num;        // 学号
		int age;        // 年龄
		char group;     // 所在小组
		float score;    // 成绩
	}class[5] = {
		{"Li ping", 5, 18, 'C', 145.0},
		{"Zhang ping", 4, 19, 'A', 130.5},
		{"He fang", 1, 18, 'A', 148.5},
		{"Cheng ling", 2, 17, 'F', 139.0},
		{"Wang ming", 3, 17, 'B', 144.5}
	};
获取Wang ming的成绩:class[4].score;
修改Li ping的学习小组:class[0].group = 'B';

 

三:C语言结构体和指针

3.1:定义结构体

指针也可以指向一个结构体,定义的形式一般为:struct 结构体名 *变量名;

实例:
	下面是一个定义结构体指针的实例:
		struct stu{
			char *name;  //姓名
			int num;  //学号
			int age;  //年龄
			char group;  //所在小组
			float score;  //成绩
		} stu1 = { "Tom", 12, 18, 'A', 136.5 };
		//结构体指针
		struct stu *pstu = &stu1;
	
	也可以在定义结构体的同时定义结构体指针:
		struct stu{
			char *name;  //姓名
			int num;  //学号
			int age;  //年龄
			char group;  //所在小组
			float score;  //成绩
		} stu1 = { "Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;

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

还应该注意,结构体和结构体变量是两个不同的概念:结构体是一种数据类型,是一种创建变量的模板,编译器不会为它分配内存空间,就像 int、float、char 这些关键字本身不占用内存一样;结构体变量才包含实实在在的数据,才需要内存来存储。

下面的写法是错误的,不可能去取一个结构体名的地址,也不能将它赋值给其他变量:

struct stu *pstu = &stu;
struct stu *pstu = stu;

3.2:获取结构体成员

两种形式(等效,通常采用后者,更加直观):

(*pointer).memberName
	.的优先级高于*,并且()也不能省略,若是省略则等价于:*(pointer.memberName)
pointer->memberName	
	有了->,就可以通过结构体指针直接去的结构体成员,这也是->在C语言中的唯一用途

看下例子:

实例1#include <stdio.h>
	int main(){
		struct{
			char *name;
			int num;
			int age;
			char group;
			float score;
		}stu1 = {"tom", 12, 18, 'A', 136.5}, *pstu = &stu1;

		// 读取结构体成员你的值
		printf("%s的学号是%d, 年龄是%d, 在%c组, 今年的成绩是%.1f \n", (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score);
		printf("%s的学号是%d, 年龄是%d, 在%c组, 今年的成绩是%.1f \n", pstu->name, pstu->num, pstu->age, pstu->group, pstu->score);
	}
结果:
	┌──(root💀kali)-[~/Desktop/c_test]
	└─# ./jiegoutizhizhen  
	tom的学号是12, 年龄是18, 在A组, 今年的成绩是136.5 
	tom的学号是12, 年龄是18, 在A组, 今年的成绩是136.5 


实例2#include <stdio.h>
	struct stu{
		char *name;     // 姓名
		int num;        // 学号
		int age;        // 年龄
		char group;     // 所在小组
		float score;    // 成绩
	}stus[] = {
		{"Zhou ping", 5, 18, 'C', 145.0},
		{"Zhang ping", 4, 19, 'A', 130.5},
		{"Liu fang", 1, 18, 'A', 148.5},
		{"Cheng ling", 2, 17, 'F', 139.0},
		{"Wang ming", 3, 17, 'B', 144.5}
	},*ps;

	int main(){
		// 求数组长度
		int len = sizeof(stus) / sizeof(struct stu);
		printf("Name\t\tNum\tAge\tGroup\tScore\t\n");
		for(ps=stus; ps<stus+len; ps++){
			printf("%s\t%d\t%d\t%c\t%.1f \n", ps->name, ps->num, ps->age, ps->group, ps->score);
		}
		return 0;
	}
结果:
┌──(root💀kali)-[~/Desktop/c_test]
└─# ./jiegoutishuzuzhizhen 
Name            Num     Age     Group   Score
Zhou ping       5       18      C       145.0 
Zhang ping      4       19      A       130.5 
Liu fang        1       18      A       148.5 
Cheng ling      2       17      F       139.0 
Wang ming       3       17      B       144.5 

 

四:C语言共用体

结构体(struct)是一种构造类型或复杂类型,可以包含多个类型不同的成员。在C语言中还有另一种和结构体非常类似的语法,叫做共用体(union)。

定义格式为:

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

区别:

  • 结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。

  • 结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存。

  • 共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。

共用体也是一种自定义类型,可以通过它来创建变量,例如:

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

上面是先定义共用体,再创建变量,也可以在定义共用体的同时创建变量:

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

共用体data中,成员f占用的内存最多,为8个字节,所以data类型的变量(也就是a,b,c)也占用8个字节的内存。

实例:
	#include <stdio.h>
	union data{
		int n;
		char ch;
		short m;
	};

	int main(){
		union data a;
		printf("%d, %d\n", sizeof(a), sizeof(union data) );
		a.n = 0x40;
		printf("%X, %c, %hX\n", a.n, a.ch, a.m);
		a.ch = '9';
		printf("%X, %c, %hX\n", a.n, a.ch, a.m);
		a.m = 0x2059;
		printf("%X, %c, %hX\n", a.n, a.ch, a.m);
		a.n = 0x3E25AD54;
		printf("%X, %c, %hX\n", a.n, a.ch, a.m);
	   
		return 0;
	}
结果:
	┌──(root💀kali)-[~/Desktop/c_test]
	└─# ./gongyongti      
	4, 4
	40, @, 40
	39, 9, 39
	2059, Y, 2059
	3E25AD54, T, AD54

这段代码不但验证了共用体的长度,还说明共用体成员之间会相互影响,修改一个成员的值会影响其他成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值