C语言学习总结(五)-----自定义类型

结构体

什么是结构体?
结构体是不同类型元素的集合体。
为什么要有结构体?
因为一个对象有很多个属性这些属性是相互联系的,例如一个学生有年龄(age),地址(adder),学号(num),姓名(name)等属性,所以数组是存储不了的(数组是同一类型元素的集合体),但是如果分开存放又难以反映出它们之间的关系,因此才有了结构体。
结构体如何使用?

结构体的声明:

struct Student
{
	char name[20];
	short age;
	char num[20];
	float socer;
};//分号不能丢

此时我们声明了一个结构体,但它仅仅是一个类型,和C语言中的int char等是一样的,系统并没有为它开辟空间,只有在定义变量后,才会开辟空间。
特殊的结构体声明:
匿名结构体类型:

struct
{
	int a;
	float b;
	double c;
}x;
struct
{
	int a;
	float b;
	double c;
}*p;
p = &x;//非法

注: 上面的两个结构体都没有名字,这样的结构体叫做匿名结构体,匿名结构体只能在声明的时候定义结构体变量。虽然上面两个结构体都是匿名结构体而且成员列表都一样,但它们仍属于两个不同的类型,所以最后一个语句是错误的。

结构体变量的定义及初始化
struct point
{
	int x;
	int y;
} p1 = {2,2};//声明类型的同时定义变量p1
struct point p2 = { 1, 3 };//定义结构体变量p2并进行初始化;
-------------------------------------------------------------
struct Node
{
	int data;
	int arr[3];
	struct point p1;
	struct Node* next;
};
struct Node n1 = { 3, { 1, 2, 3 }, { 1, 2 }, NULL };

总的来说,结构体的初始化和数组是一样的。
只能整体初始化,不能整体赋值

当结构体内嵌套结构体时,采用大括号套大括号的方式进行初始化。

结构体的自引用:
如果一个结构体的成员变量中包含自身,就叫做结构体的自引用

struct Node
{
	int data;
	struct Node next;
};

这种自引用方式显然是错误的,因为Node中有一个next,而next中还有下一个next,下一个next中含有下一个next…(子子孙孙无穷尽焉)。
如图:
在这里插入图片描述

正确的自引用方式:

struct Node
{
	int data;
	struct Node* next;
};

这正如数据结构中链表的节点一样!
结构体成员的访问方式:

struct A
{
	int b;
	char c;
};
int main()
{
	struct A a = { 1, 'h' };
	struct A* pa = &a;
	printf("%d %c\n", a.b, pa->c);
	system("pause");
	return 0;
}

可见结构体成员的访问总共有两种方式:
1.结构体变量名.成员名
2.结构体指针->成员名

结构体传参

函数在调用的时候要生成栈帧结构,参数要入栈,因此要开辟空间,而且结构体传参的时候不像数组会发生降级,因此如果结构体自身所占空间过大,势必在硬拷贝的情况下导致性能的下降。
结论:结构体传参的时候,传结构体指针。

枚举

enum关键字,专门用来定义枚举类型,这也是它在C语言中的唯一用途。

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

像结构体一样,此时仅仅声明了一个枚举类型,并没有定义枚举变量。枚举中的成员统称为枚举常量,和普通常量一样,枚举常量也只能作为右值,不能作为左值。

enum num
{
	a,
	b = 0,
	c,
	d = 4,
	e
};
int main()
{
	printf("%d\n", a);
	printf("%d\n", b);
	printf("%d\n", c);
	printf("%d\n", d);
	printf("%d\n", e);

	system("pause");
	return 0;
}

在这里插入图片描述
可以看出枚举常量的值默认从0开始,后面的数比前一个数多1.
枚举的优点(相较于宏)
1.增加代码的可读性,可维护性。
2.枚举有类型,更加严谨。
3.防止命名污染。
4.便于调试。
5.使用方便,一次可以定义多个枚举常量。

联合体(共用体)

用union关键字来声明联合体,联合也是一种自定义类型,像结构体一样也包括很多成员变量,但这些成员变量共用一块内存空间 。因此联合体也叫共用体 。
因为联合体是用用一块内存空间的,因此一个联合体的大小,至少是其内部最大成员变量的大小(最大指的是所占内存最大)。
联合体的大小

union Un
{
	char arr[10];
	int b;
};
int main()
{
	printf("%d\n", sizeof(union Un));
	system("pause");
	return 0;
}

输出:12.这里应该是10,但结果是12 是因为内存对齐的缘故。

union Un
{
	char i;
	int b;
};
int main()
{
	union Un un;
	printf("%p\n", &(un.i));
	printf("%p\n", &(un.b));

	system("pause");
	return 0;
}

输出:
在这里插入图片描述
在这里操作系统给联合体分配四个字节,验证得出i存储在四个字节中地址最低的字节中。利用这个特点,我们可以利用联合体来验证计算机的大小端存储模式,代码如下:

union Un
{
	char i;
	int b;
};
int main()
{
	union Un un;
	un.b = 1;
	if (un.i == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}	
	system("pause");
	return 0;
}

tip:在定义声明类型的时候,我们可以用typedef对其进行类型重命名从而进行简化!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值