当前位置:网站首页>【C语言】自定义类型初阶知识点
【C语言】自定义类型初阶知识点
2022-07-17 10:21:00 【安苒_】
文章目录
一、结构体
1.关于C的结构体
定义:
结构体是把一些相关的变量组合起来,以一个整体形式对对象进行描述。
注意:
1.只有结构体变量才分配地址,而结构体的定义是不分配空间的。
2.结构体中各成员的定义和之前的变量定义一样,但在定义时也不分配空间。
3.结构体变量的声明需要在主函数之上或者主函数中声明,如果在主函数之下则会报错。
4.c语言中的结构体不能直接进行强制转换,只有结构体指针才能进行强制转换。
5.相同类型的成员变量是可以定义在同一类型下的
2.结构体类型的声明
//一般声明
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}; //分号不能丢
//匿名结构体类型
struct
{
int a;
char b;
float c;
}x;
struct
{
int a;
char b;
float c;
}a[20], *p;
//在匿名结构体类型声明代码的基础上,下面的代码不合法
p = &x;
//原因:上面的两个结构在声明的时候省略掉了结构体标签(tag)
//编译器会把上面的两个声明当成完全不同的两个类型。
//所以是非法的。
//“复合型”声明——自取的名字
//结构中包含一个类型为该结构本身的成员即结构体的自引用,链表处使用非常常见
struct Node
{
int data;
struct Node* next;
};
//另外
typedef struct
{
int data;
Node* next;
}Node;
//这样写代码,不行
//解决方案:
typedef struct Node
{
int data;
struct Node* next;
}Node;
3.结构体变量的定义和初始化
定义
struct Point
{
int x;
int y;
}p1; //方式一:声明类型的同时定义变量
struct Point p2; //方式二:单独定义结构体变量
初始化
//一般初始化、嵌套初始化
//方式一
struct Point p3 = {
x, y};
struct Stu
{
char name[15];
int age;
};
struct Stu s = {
"zhangsan", 20};//一般初始化
//方式二
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {
10, {
4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {
20, {
5, 6}, NULL};//结构体嵌套初始化
4.结构体成员访问
结构变量
的成员是通过点操作符(.)
访问的。点操作符接受两个操作数。
结构体指针
通过->或(*)
访问结构体成员变量。
//结构体变量
struct S s;
strcpy(s.name, "zhangsan");//使用.访问name成员
s.age = 20;//使用.访问age成员
//结构体指针
struct Stu
{
char name[20];
int age;
};
void print(struct Stu* ps)
{
printf("name = %s age = %d\n", (*ps).name, (*ps).age);
//使用结构体指针访问指向对象的成员
printf("name = %s age = %d\n", ps->name, ps->age);
}
int main()
{
struct Stu s = {
"zhangsan", 20};
print(&s);//结构体地址传参
return 0;
}
5.结构体传参
结构体传参的时候,要传结构体的地址。
原因:函数传参时,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
//例子——首选传址即首选print2
struct S
{
int data[1000];
int num;
};
struct S s = {
{
1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
{
printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
printf("%d\n", ps->num);
}
int main()
{
print1(s); //传结构体
print2(&s); //传地址
return 0;
}
二、枚举
1.枚举类型的定义
enum DAY{
MON=1,TUE,WED,THU,FRI};
enum DAY day;
enum DAY{
MON=1,TUE,WED,THU,FRI}day;//也可以在定义枚举类型时一起定义
enum{
MON=1, TUE, WED, THU, FRI, SAT, SUN}day;//可以省略枚举名称
//枚举实例:星期、性别、颜色等
//枚举类型:enum x
//注意这里是逗号
//{}中的内容是枚举类型的可能取值,也叫枚举常量。
//这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值
enum Day//星期
{
Mon,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum Sex//性别
{
MALE,
FEMALE,
SECRET
};
enum Color//颜色
{
RED=1,
GREEN=2,
BLUE=4
};
2.枚举的优点
增加代码的可读性和可维护性
使用方便,一次可以定义多个常量,和#define定义的标识符比较枚举有类型检查,更加严谨。
#define MON 1
#define TUE 2
#define WED 3
#define THU 4
#define FRI 5
#define SAT 6
#define SUN 7<==>enum DAY{MON=1,TUE,WED, THU, FRI, SAT, SUN};
防止了命名污染(封装)
便于调试
3.枚举的使用
枚举变量
#include <stdio.h>
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
};
int main()
{
enum DAY day;
day = WED;
printf("%d",day);
return 0;
}
枚举类型的遍历
#include <stdio.h>
enum DAY
{
MON=1, TUE, WED, THU, FRI, SAT, SUN
} day;
int main()
{
// 遍历枚举元素
for (day = MON; day <= SUN; day++) {
printf("枚举元素:%d \n", day);
}
}
//输出结果
枚举元素:1
枚举元素:2
枚举元素:3
枚举元素:4
枚举元素:5
枚举元素:6
枚举元素:7
//像以下枚举类型不连续,则无法进行遍历
#include<stdio.h>
enum DAY
{
MON=1, TUE, WED, THU=6, FRI, SAT, SUN
}day;
int main()
{
for(day=MON;day<=SUN;day++)
{
printf("%d\t",day);
}
return 0;
}
//以上的输出结果会变成 1 2 3 4 5 6 7 8 9
将整数转换为枚举
#include<stdio.h>
#include<stdlib.h>
int main()
{
enum day{
saturday,sunday,monday,tuesday,wednesday,thursday,friday}workday;
int a=1;
enum day weekend;
weekend=(enum day)a;
printf("weekend:%d",weekend);
return 0;
}
//输出结果:weekend:1
三、联合(共用体)
1.联合类型的定义
由联合体类型定义的变量包含一系列的成员,与结构体定义类似,特征是这些成员共用同一块空间
(所以联合也叫共用体)。
union 共用体名
{
成员表列
}变量表列;
2.联合的特点
特点
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。
不是每个成员都有自己的空间。【类比合租(联合/共用体)和独立房间(结构体)的概念】
一个例子
union Un
{
int i;
char c;
};
union Un un;
// 下面输出的结果是不一样的
printf("%d\n", &(un.i));//1
printf("%d\n", &(un.c));//2
//下面输出的结果
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);//3
//输出结果
-1399655116——随机值
-1399655116
11223355
为什么第三次打印会出现那样的结果呢?
因为 un.c = 0x55;改掉了un.i低地址处一个字节的值【共用内存】
3.联合的应用
共用体在一般的编程中应用较少,在单片机中应用较多。对于 PC 机,经常使用到的一个实例是: 现有一张关于学生信息和教师信息的表格。学生信息包括姓名、编号、性别、职业、分数,教师的信息包括姓名、编号、性别、职业、教学科目。
4.一道面试题
判断当前计算机的大小端存储
#include <stdio.h>
//方法一:利用指针
int check_sys1()
{
int a = 1;
return *(char*)&a;
}
//方法二:利用联合体
int check_sys2()
{
union Un
{
int i;
char c;
}u;
u.i = 1;
return u.c;
}
int main()
{
int ret1 = check_sys1();
if (ret1 == 1)
printf("小端\n");
else
printf("大端\n");
int ret2 = check_sys2();
if (ret2 == 1)
printf("小端\n");
else
printf("大端\n");
return 0;
}
边栏推荐
- 组件化高级--插槽
- Anycontrol demo demo demo
- 如何在监控主机上单独部署agent——WGCLOUD
- 【微服务~高级】配置中心实战
- Use < pre > and json Stringify handles the format of web page presentation JSON
- 【愚公系列】2022年7月 Go教学课程 012-强制类型转换
- 【Flink】Flink 设置检查点失败一次就报错 setTolerableCheckpointFailureNumber 不起作用
- cookie和session在实际项目中的使用
- 【网络研究院】机器学习系统的威胁是时候该认真对待了
- Log desensitization - Reference
猜你喜欢
C language compilation process
【排错必看】Windows系统安装mysql时常见问题及解决方法
Anycontrol demo demo demo
Log desensitization - Reference
2、 Pinda general permission system__ Project construction
C语言基础篇 —— 2-1 指针与野指针
How is MySQL data stored on disk?
Data Lake (20): Flink is compatible with iceberg, which is currently insufficient, and iceberg is compared with Hudi
两个结构体 ifconf 和 ifreq
Microservice splitting for stand-alone projects
随机推荐
SAP Fiori 的附件处理(Attachment handling)
电脑拨号上网
MySQL initialization and password modification
06---光在介质中的特性
Tree array
DuiLib 实现tooltip自定义鼠标提示窗口
v-mode
un7.16:如何在码云上部署项目并邀请组员?
Un7.16: how to deploy projects on code cloud and invite team members?
MySQL 视图
[hero planet July training leetcode problem solving daily] 17th kuansou
MySQL--SQL优化案例--隐式字符编码转换
【微服务~高级】配置中心实战
面试题-给::memcpy函数设计测试用例
SAP Fiori 的附件处理(Attachment handling)
sql server建表时设置ID字段自增 (navicat 演示)
L2-029 independent happiness
Yanrong technology was selected as Beijing's "specialized and innovative" in 2022 to lead hybrid cloud file storage
Scope and lifecycle of beans
mysql进阶(六)模糊查询的四种常见用法介绍