结构与联合

本文深入探讨了结构体和联合体的概念与应用,讲解了结构体的定义、使用及运算,包括初始化、成员访问、作为函数参数的传递,以及结构体指针的使用。同时,介绍了联合体的基本原理,通过实例展示了如何获取整型和双精度浮点型内部的字节表示。

为什么需要结构体?

为了表示一些复杂的事物,而普通的基本类型无法满足实际要求

什么是结构体?

把一些基本类型数据组合在一起形成一个新的复合数据类型,这种新的类型叫做结构体

如何定义一个结构体?

struct Student {
	int age;
	float score;
	char sex;
};

struct Student st1,st2;
//st1,st2都是student 里面有x和y的值

struct Student2 {
	int age;
	float score;
	char sex;
}st2;
st2是Student2

struct {
	int age;
	float score;
	char sex;
}st3;
st3是一种无名结构,里面有x和y
没有声明Student只是定义了一个变量st3

推荐使用第一种方式:

  • 结构体名称+结构体变量名称*

结构成员
结构和数组有点像
但是可以是不同的数据类型
访问方式:

  • 数组 []运算符下标访问其成员
  • 结构用 . 运算符名字访问其成员

怎么使用结构体变量

  • 赋值和初始化
    初始化可以整体
    赋值只能单个地进行
int main(void)
{
	struct Student st = { 80,66.6,'F' };
	//初始化 定义的同时赋初始值
	struct Student st2;
	st2 = st;
	//在数组中不可以实现
	st2.age = 10;
	st2.score = 88;
	st2.sex = 'F';
	printf("%d %f %c\n", st.age, st.score, st.sex);
	printf("%d %f %c\n", st2.age, st2.score, st2.sex);

}
  • 如何取出结构体变量中的每一个成员

    1.结构体变量名.成员名

    2.指针变量名->成员名(第二种更加常用)

int main(void)
{
	struct Student st = { 80,66.6,'F' };
	struct Student* pst = &st;
	st.age = 70;
	//方式一
	pst->age = 88;
	//方式二
	printf("%d", st.age);

	pst->score = 66.6f;
	/*66.6在C语言中默认是double类型
	如果希望一个实数是float类型
	则必须在末尾加f或F
	66.6是double
	66.6f是float*/
	
	printf("%f",st.score)
	/*输出结果是66.59998
	浮点数不能够准确存储每一位小数
	只能存一个近似值*/
}

pst->age在计算机内部会被转化成(*pst).age
(硬性规定叭)

pst所指向的那个结构体变量中的age成员

  • 结构体变量和结构体变量指针作为函数参数传递的问题

    结构体的输入和输出

#include<stdio.h>
#include<string.h>
struct Student {
	int age;
	char score;
	char name[100];
};
//定义类型
int main(int argc, char const* argv[])
{
	struct Student st = { 80,'F',"李四" };
	InputStudent(&st);//对结构体变量输入
	printf("%d %c %s\n", st.age, st.score, st.name);
}
int InputStudent(struct Student *pstu)//pstu只占四个字节
{
	pstu->age = 10;
	strcpy_s(pstu->name,8,"张三");//不能写成 stu.name = "张三";
	pstu->score = 'F';
}
/*
示例:
	发送指针还是发送内容
目的:
	指针使用的优点:
		可以快速传递数据
		内存占据小
		执行速度快
对结构体变量输入:
	必须用指针
对结构体变量输出:
	都可,建议指针
*/

推荐使用结构体指针变量作为函数参数传递的问题

  • 结构体变量的运算
    结构体变量不能相加,不能相减法,也不能乘除
    但结构体变量可以相互赋值

函数题:

输入:今天的日期
输出:明天的日期
#include<stdio.h>
#include<stdbool.h>

struct date {
	int month;
	int day;
	int year;
};
/*将输入的年份以结构体的形式存在*/

bool isLeap(struct date d);
//判断闰年与否
int numberOfDays(struct date d);
//返回每个月的天数 并借用闰年函数来检验2月的天数

int main(int argc, char const* argv[])
{
	struct date today, tomorrow;
	printf("Enter today's data(mm dd yyyy:)");
	scanf_s("%d %d %d", &today.month, &today.day, &today.year);

	if (today.day != numberOfDays(today)) {
		tomorrow.day = today.day + 1 ;
		tomorrow.month = today.month;
		tomorrow.year = today.year;
	}
	else if (today.month == 12) {
		tomorrow.day = 1;
		tomorrow.month = 1;
		tomorrow.year = today.year + 1;
	}else{
		tomorrow.day = 1;
		tomorrow.month = today.month + 1;
		tomorrow.year = today.year;
	}
	printf("Tomorrow's date is %d-%d-%d.\n",
		tomorrow.year, tomorrow.month, tomorrow.day);

	return 0;
}

int numberOfDays(struct date d)
{
	int days;

	const int daysPerMonth[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };

	if (d.month == 2 && isLeap(d)) {
		days = 29;
	}else {
		days = daysPerMonth[d.month - 1];
	}

	return days;
}

bool isLeap(struct date d)
{
	bool leap = false;

	if ((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 100 == 0) {
		leap = true;
	}

	return leap;
}

输入:12:59:59
输出:13:00:00

#include<stdio.h>
struct time {
	int hour;
	int minutes;
	int seconds;
};
struct time timeUpdate(struct time now);

int main(void)
{
	struct time testTimes;
	printf("Enter time is\n");
	scanf_s("%d:%d:%d", 
		&testTimes.hour,&testTimes.minutes,&testTimes.seconds);
	testTimes = timeUpdate(testTimes);
	printf("...one second later it is %.2d:%.2d:%.2d\n",
	testTimes.hour, testTimes.minutes, testTimes.seconds);

	return 0;
}

struct time timeUpdate(struct time now)
{
	++now.seconds;
	if (now.seconds == 60) {
		now.seconds = 0;
		++now.minutes;

		if (now.minutes == 60) {
			now.minutes = 0;
			++now.hour;

			if (now.hour == 24) {
				now.hour = 0;
			}
		}
	}
	return now;
}
//结构中的结构

#include<stdio.h>
struct point {
	int x;
	int y;
};

struct rectangle {
	struct point p1;
	struct point p2;
};

void printRect(struct rectangle r)
{
	printf("<%d %d> to <%d %d>\n", r.p1.x, r.p1.y, r.p2.x, r.p2.y);
}

int main(int argc, char const* argv[])
{
	int i;
	struct rectangle rects[] =
	{
		{{1,2},{3,4}},
	{{5,6},{7,8}}
	};
	for (i = 0; i < 2; i++) {
		printRect(rects[i]);
	}

	return 0;
}

自定义数据类型(typedef)
tyoedef int Length
Length成为了int类型的别名

Length a,b,len;
Length numbers[10];

Length这个名字就可以代替int出现在变量定义和参数声明的地方

typedef struct ADate{
	int month;
	int day;
	int year;
}Date;

struct ADate取了一个叫做Date的别名

Date d = { 9,1,2005 };

改善了程序的可读性

typedef struct{
	int month;
	int day;
	int year;
}Date;

这样的struct叫做Date

用typedef说明一种新类型名

typedef 类型名 标识符

实际上并没有产生新的数据类型
原有类型名依然有效,这样做可以满足一些特殊情况的需要

联合union/ 共用体

得到一个int内部的字节
或是得到一个double内部的字节

#include<stdio.h>

typedef union {
	int i;
	char ch[sizeof(int)];
}CHI;

int main(int argc, char const* argv[])
{
	CHI chi;
	int i;
	chi.i = 1234;
	//十六进制0X04D2
	for (i = 0; i < sizeof(int); i++) {
		printf("%02hhX", chi.ch[i]);
	}
	printf("\n");
/*输出结果D2040000*/
	return 0;
}

x86 小端 低位在前

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值