C语言结构体

结构体、共用体、枚举、宏定义、预处理

1.1、结构体
1.1.1、为什么需要结构体?

没有结构体之前,在C语言中,数据的组织依靠:变量+数组。
最初最简单的时候,只需要使用基本数据类型(int char float double)来定义单个变量,需要几个变量就定义几个。
后来情况变复杂了,有时需要很多意义相关的变量(譬如需要存储及运算一个班级的学生分数)这时候数组出现了。数组解决了需要很多类型相同、意义相关的变量的问题。
但是数组是有限制的。数组最大的不足在于,一个数组只能存储很多个数据类型相同的变量。
所以碰到需要封装几个类型不同的变量的时候,数组就无能为力。
练习题目:使用一个数据结构来保存一个学生的所有信息:姓名 学号 性别
这时候就需要结构体。

#include <stdio.h>


// 注意:
// 1、结构体类型的定义是在函数外面,不是里面
// 2、结构体定义的是一个新的组合类型,而不是变量,也不消耗内存。
//    稍后在定义变量的地方,再使用该结构体类型来定义变量。
struct Student
{
	char name[20];				// 学生姓名
	unsigned int num;			// 学号
	int isMale;					// 性别
};

1.2、什么是结构体?
结构体是一个集合,集合中包含很多个元素,这些元素的数据类型可以相同,也可以不相同。所以结构体是一种数据封装的方法。结构体存在的意义就在于,把很多数据类型不相同的变量封装在一起,组成一个大的新的数据类型。

数据结构:把庞大复杂的数据用一定的方式组织管理起来,便于操作(查找,增加,删除等),这就叫数据结构。
练习题目:结构体中的数据类型可以不同

struct MyStruct
{
	int a;
	char c;
	float f;
	double d;
};						// 注意这里的;不能少

int main(void)
{
	//struct MyStruct s = {100, 'd', 12.445, 111.111111111111};	// ok
	//struct MyStruct s = {100; 'd'; 12.445; 111.111111111111};	// 不行
	
	
/*	
	// 这种部分ok的是最危险的,千万不用。

	struct MyStruct s = 
		{
			s.a = 1444, 					// 只能从前到后依次初始化,中间只要空一个,后面就出问题
			s.c = 'k', 						
			s.f = 3.13,
			//s.d = 32.222222,
		};										// 部分ok
*/	

1.3、结构体和数组的关联
数组是一种特殊的结构体,特殊之处在于封装内的各个元素类型是相同的。结构体和数组都是对一些子元素的封装,因此定义的时候都是封装作为整体定义,但是使用的时候,都是使用封装中的子元素。一般结构体变量和数组变量都不会作为一个整体操作。

1.4、使用结构体的步骤
第一步:定义结构体类型。结构体类型的定义是在函数外面(函数外面 == 全局)的
第二步:使用第一步定义的类型来定义结构体变量。
第三步:使用变量。实际上使用结构体变量的时候,使用的是结构体变量中封装的各个子元素,而不是结构体变量本身。

1.5、结构体的初始化
结构体变量和普通变量一样,作为局部变量时,如果定义的时候无初始化也无显式赋值,则结构体变量中的子元素的值是随机的。

发现2种C语言接受的结构体初始化方式。
第一种,完全初始化。{xx, xx, xx, xx, xx};
第二种,部分初始化。
{
.a = xx,
.b = xx,
.c = xx,
.d = xx,
};

新增关键字: struct
新增操作符: .

1.6、共用体(union,联合,联合体)
共用体union在定义和使用形式上,和结构体struct很相似。但是两种数据结构是完全不同的两类东西。
结构体,是对多个数据的组合与封装。
共用体,共用体中只有一个东西,只是它被好几个名字(和类型)共用。

练习题目:C语言结构体定义的演示,初步了解结构体的定义方式及含义

#include <stdio.h>


// 定义共用体类型
union MyUnion
{
	int a;
	char b;
	float c;
};



int main(void)
{
	union MyUnion u1;		// 使用自定义的union类型来定义变量
	
	u1.a = 12933;
	
	printf("u1.a = %d, u1.b = %d.\n", u1.a, u1.b);
	
	return 0;
}
char 的范围:-128 ~ 127
int 的范围:-xxxx ~ + xxxx
所以上面的练习题目中,u1.a的值在-128~127的范围内的时候,u1.b=u1.a

新增关键字:union

练习题目:结构体和共用体的使用

#include <stdio.h>

struct Male
{
	int age;
	char name[20];
	int basketball;
};

struct Female
{
	int age;
	char name[20];
	int aerobics;
};

union student
{
	struct Male m;
	struct Female f;
};

int main(void)
{
	union student s[30];		// 数组,定义了一个班的30个学生
	s[0].m.basketball = 47;
	
	s[1].f.aerobics = 44;
}

1.7、宏定义

#define N 321			//宏定义的格式

宏定义要注意的问题:
1、宏定义一般是在函数的外面
2、宏定义必须要先定义,再使用宏。如果先使用就会编译报错。
3、宏定义中宏名一般用大写。不是语法规定的,是一般约定俗成的。
练习题目:C语言宏定义的演示

#include <stdio.h>

#define N (10)			// 宏定义

#define M (10 + N)

#define PI	(3.14)

#define S(r) (PI * (r) * (r))		// 计算园面积的宏
#define L(r) (2 * PI * (r))			// 计算圆的周长的宏

// 题目,使用宏定义定义一个宏,表示一年中的秒数
#define SEC_PER_YEAR (365 * 24 * 60 * 60)UL


int main(void)
{
	int a[N] = {1, 2, 3};
	int b[N];
	int c[N];
	
	
	printf("sizeof(c) = %d.\n", sizeof(c));

/*
	int a;
	
	a = 123;
	a = N;
	
	
	printf("a = %d.\n", a);
*/
	
	return 0;
}

为什么使用宏定义?
在C语言中,一般使用常数的时候,都不是直接使用,而是先把该常数定义为一个宏,然后在程序中使用该宏名。这样做的好处是,等我们需要修改这个常数时,只需要在宏定义处修改一次即可。而不用到代码中到处去寻找,看哪里都用过该常数。

1.7、枚举
练习题目:C语言枚举的使用,理解枚举和宏定义的不同

#include <stdio.h>

/*
#define SUN	0
#define MON 1
#define TUE	2
#define WEN	3
#define THR	4
#define FRI	5
#define SAT	6

#define N 10
*/


// 定义一个枚举类型,名字叫enum week
enum week
{
	SUN,		// SUN = 0
	MON,		// MON = 1;
	TUE,
	WEN,
	THR,
	FRI,
	SAT,
};




int main(void)
{
	enum week today;		// 使用enum week类型,来定义一个枚举变量today
	
	today = SAT;
	
	switch (today)
	{
		case MON:
			printf("hao kun a.\n");
			break;
		case TUE:
			printf("2\n");
			break;
		case WEN:
			printf("3.\n");
			break;
		case THR:
			printf("4\n");
			break;
		case FRI:
			printf("5.\n");
			break;
		case SAT:
			printf("6\n");
			break;
		case SUN:
			printf("ha ha.\n");
			break;
		default:
			printf("bu ke neng.\n");
			break;
	}
//输出为6.

/*
	int day;
	
	day = N;
	
	switch (day)
	{
		case MON:
			printf("hao kun a.\n");
			break;
		case TUE:
			printf("2\n");
			break;
		case WEN:
			printf("3.\n");
			break;
		case THR:
			printf("4\n");
			break;
		case FRI:
			printf("5.\n");
			break;
		case SAT:
			printf("6\n");
			break;
		case SUN:
			printf("ha ha.\n");
			break;
		default:
			printf("bu ke neng.\n");
			break;
	}
*/输出为bu ke neng.

	
	return 0;
}

基础知识:
1、double float用%f打印,
2、char用%c和%d打印,
3、int用%d打印
4、字符串用%s打印,
5、指针用%p打印

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值