当前位置:网站首页>【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.枚举的优点

  1. 增加代码的可读性和可维护性

  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};

  1. 防止了命名污染(封装)

  2. 便于调试

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;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HucmWmBZ-1657963625121)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715112749501.png)]

枚举类型的遍历

#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 共用体名
{
    成员表列
}变量表列;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DEn7Z3BI-1657963625123)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715120402429.png)]

2.联合的特点

特点

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。

不是每个成员都有自己的空间。【类比合租(联合/共用体)和独立房间(结构体)的概念】

。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tGtGs9Xy-1657963625125)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715121210339.png)]

一个例子

	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;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N1QaIclD-1657963625127)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715131326757.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ia0AsqIz-1657963625129)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715133141566.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HlVhIqgF-1657963625130)(C:\Users\19271\AppData\Roaming\Typora\typora-user-images\image-20220715133202008.png)]

结构体参考

枚举参考

原网站

版权声明
本文为[安苒_]所创,转载请带上原文链接,感谢
https://blog.csdn.net/moteandsunlight/article/details/125822655