C语言学习之路(基础篇)—— 复合类型(自定义类型)

说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

结构体

1) 概述

数组:描述一组具有相同类型数据的有序集合,用于处理大量相同类型的数据运算。

结构体:将多个相同或不同类型的数据存在在一块连续的内存空间中。

有时我们需要将不同类型的数据组合成一个有机的整体,如:一个学生有学号/姓名/性别/年龄/地址等属性。显然单独定义以上变量比较繁琐,数据不便于管理。

语言中给出了另一种构造数据类型——结构体。
在这里插入图片描述

2) 结构体变量的定义和初始化

定义结构体变量的方式:

  • 先声明结构体类型再定义变量名
  • 在声明类型的同时定义变量
  • 直接定义结构体类型变量(无类型名)

在这里插入图片描述

结构体类型和结构体变量关系:

  • 结构体类型:指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际内存单元。
  • 结构体变量:系统根据结构体类型(内部成员状况)为之分配空间。

示例1:定义一个结构体数据类型

// 定义一个结构体数据类型
// 关键字 struct 代表这个是一个结构体类型,
// stu   是这个结构的名字
// 整个结构体的类型是   struct  stu
// 结构体类型struct  stu   {}中是结构体的成员,一个有3个成员,每个成员的类型可以是
// 任意的类型
// 定义结构体类型时,{}后面记得加分号
// 注意定义结构struct  stu,它只是一个类型,一个模板,没有空间,不可以给结构体成员赋值
struct stu
{
    
    
	int id;
	int age;
	char name[128];
}; 
int main()
{
    
    

	return 0;
}

示例2:定义结构体变量

// 第一种常用定义方式
struct stu
{
    
    
	int id;
	int age;
	char name[128];
}a; //定义类型时,同时定义了一个结构体变量,相当于struct  stu a;

struct stu2
{
    
    
	int id;
	int age;
	char name[128];
}a,b; //定义类型时,同时定义了两个结构体变量,相当于struct  stu a,b;
// 第二种常用定义方式(用的最多)
struct stu
{
    
    
	int id;
	int age;
	char name[128];
};
struct  stu c;
int main()
{
    
    

	return 0;
}
// 第三种常用定义方式(用的很少)
struct
{
    
    
	int id;
	int age;
	char name[128];
}a;

示例3:结构体变量的初始化

//结构体类型的定义
struct stu
{
    
    	
	int id;
	int age;
	char name[128];
};

//先定义类型,再定义变量(常用)
struct stu s1 = {
    
     1, 18, "cdtaogang" };


//定义类型同时定义变量
struct stu2
{
    
    	
	int id;
	int age;
	char name[128];
}s2 = {
    
     .age=22 }; // 给部分成员初始化,其他成员内容为0

struct
{
    
    	
	int id;
	int age;
	char name[128];
}s3 = {
    
     "yuri", 25 };

3) 结构体成员的使用

示例1:通过结构体变量操作结构体成员,使用点域.操作

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

// 定义一个结构体数据类型
struct stu
{
    
    
	int id;
	int age;
	char name[128];
}a; //定义类型时,同时定义了一个结构体变量,相当于struct  stu a;
struct  stu b;
int main()
{
    
    	
	//struct  stu c = {1,20,"cdtaogang"};
	//struct  stu c = { .age=20 };//给部分成员初始化,其他成员内容为0
	struct  stu d;
	//如何给结构体成员赋值(如何操作结构体成员)
	//通过结构体变量操作结构体成员,使用点域.操作
	d.id = 2;
	d.age = 20;
	//d.name = "cdtaogang"; // error 数组名是一个常量,不能被赋值
	strcpy(d.name , "cdtaogang"); 
	printf("%d %d %s\n",d.id,d.age,d.name);
	return 0;
}

示例2:通过结构体的地址操作结构体成员,使用指向->操作

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

// 定义一个结构体数据类型
struct stu
{
    
    
	int id;
	int age;
	char name[128];
}a; //定义类型时,同时定义了一个结构体变量,相当于struct  stu a;
struct  stu b;
int main()
{
    
    	
	struct  stu d;
	// 通过结构体的地址操作结构体成员,使用->
	(&d)->id = 3;
	(&d)->age = 21;
	strcpy((&d)->name, "cdtaogang");
	printf("%d %d %s\n", (&d)->id, (&d)->age, (&d)->name);
	return 0;
}

在这里插入图片描述

4) 结构体数组

结构体数组:是一个数组,数组的每一个元素都是结构体

在这里插入图片描述

示例:定义一个结构体数组

#include <stdio.h>


struct stu
{
    
    	
	int id;
	int age;
	char name[128];
};

int main()
{
    
    	
	// 定义一个结构体数组,结构体数组有5个元素,每个元素是struct stu类型
	struct stu data[5] = {
    
     {
    
    1,20,"laowang"},{
    
    2,21,"lihao"},{
    
    3,22,"cdtaogang"},{
    
    4,23,"zhaoqiang"},{
    
    5,24,"wangwu"} };
	
	for (int i = 0; i < sizeof(data)/sizeof(data[0]); i++)
	{
    
    
		printf("%d %d %s\n", data[i].id, data[i].age, data[i].name);
	}
	
	return 0;
}
输出结果
1 20 laowang
2 21 lihao
3 22 cdtaogang
4 23 zhaoqiang
5 24 wangwu

案例:统计学生成绩

#include <stdio.h>

//统计学生成绩
struct stu2
{
    
    
	int num;
	char name[20];
	char sex;
	float score;
};

int main()
{
    
    
	//定义一个含有5个元素的结构体数组并将其初始化
	struct stu2 boy[5] = {
    
    
		{
    
     101, "Li ping", 'M', 45 },
		{
    
     102, "Zhang ping", 'M', 62.5 },
		{
    
     103, "He fang", 'F', 92.5 },
		{
    
     104, "Cheng ling", 'F', 87 },
		{
    
     105, "Wang ming", 'M', 58 } };

	int i = 0;
	int c = 0;
	float ave, s = 0;
	for (i = 0; i < 5; i++)
	{
    
    
		s += boy[i].score;	//计算总分
		if (boy[i].score < 60)
		{
    
    
			c += 1;		//统计不及格人的分数
		}
	}

	printf("s=%f\n", s);//打印总分数
	ave = s / 5;					//计算平均分数
	printf("average=%f\ncount=%d\n\n", ave, c); //打印平均分与不及格人数

	for (i = 0; i < 5; i++)
	{
    
    
		printf(" name=%s,  score=%f\n", boy[i].name, boy[i].score);
		// printf(" name=%s,  score=%f\n", (boy+i)->name, (boy+i)->score);
	}

	return 0;
}

在这里插入图片描述

5) 结构体套结构体

示例:结构体套结构体

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct stu
{
    
    
	int id;
	int age;
	char name[128];
};

struct cls_stu
{
    
    
	/*int id;
	int age;
	char name[128];*/
	struct stu s;
	char subject[128];
};

int main()
{
    
    
	struct cls_stu cs;
	cs.s.id = 1;
	cs.s.age = 20;
	strcpy(cs.s.name, "cdtaogang");
	strcpy(cs.subject, "c/c++");
	printf("id=%d, age=%d, name=%s, subject=%s", cs.s.id, cs.s.age, cs.s.name, cs.subject);

	return 0;
}
输出结果
id=1, age=20, name=cdtaogang, subject=c/c++

6) 结构体赋值

示例1:第一种方法

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>


struct stu
{
    
    
	int id;
	int age;
	char name[128];
};

void memcpy_str(struct stu *x, struct stu* y)
{
    
    
	memcpy(x, y, sizeof(*x));

}

int main()
{
    
    
	struct stu a;
	struct stu b = {
    
     1, 22, "cdtaogang" };
	//memcpy(&a, &b, sizeof(a));
	memcpy_str(&a, &b); //将上面改为函数调用实现形参改变实参的值
	printf("%d %d %s\n", a.id, a.age, a.name);

	return 0;
}

示例2:第二种方法

int main()
{
    
    
	struct stu a;
	struct stu b = {
    
     1, 22, "cdtaogang" };
	// 第一种方法
	//memcpy(&a, &b, sizeof(a));
	//memcpy_str(&a, &b);
	// 第二种方法
	a.id = b.id;
	a.age = b.age;
	strcpy(a.name, b.name);
	printf("%d %d %s\n", a.id, a.age, a.name);

	return 0;
}

示例3:第三种方法

int main()
{
    
    
	struct stu a;
	struct stu b = {
    
     1, 22, "cdtaogang" };
	// 第一种方法
	//memcpy(&a, &b, sizeof(a));
	//memcpy_str(&a, &b);
	// 第二种方法
	/*a.id = b.id;
	a.age = b.age;
	strcpy(a.name, b.name);*/
	// 第三种方法
	// a = b 内核实现的原理就是memcpy(&a, &b, sizeof(a));
	a = b; // 相同类型的变量是可以相互赋值
	printf("%d %d %s\n", a.id, a.age, a.name);

	return 0;
}

在这里插入图片描述

7) 结构体和指针*

7.1 指向普通结构体变量的指针

示例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


struct stu
{
    
    
	int id;
	int age;
	char name[128];
};

int main()
{
    
    
	//struct stu* p; // error 野指针 没有初始化,指向随机
	// 第一种方式
	struct stu s;
	struct stu* p = &s;
	(*p).id = 1;
	(*p).age = 20;
	strcpy((*p).name,"cdtaogang");

	printf("(*p).id=%d, (*p).age=%d, (*p).name=%s", (*p).id, (*p).age, (*p).name);

	return 0;
}
输出结果
(*p).id=1, (*p).age=20, (*p).name=cdtaogang

7.2 堆区结构体变量

示例:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


struct stu
{
    
    
	int id;
	int age;
	char name[128];
};

int main()
{
    
    
	//struct stu* p; // error 野指针 没有初始化,指向随机
	// 第一种方式
	/*struct stu s;
	struct stu* p = &s;*/
	// 第二种方式
	struct stu* p = malloc(sizeof(struct stu));
	p->id = 1;
	p->age = 20;
	strcpy(p->name, "cdtaogang");

	printf("p->id=%d, p->age=%d, p->name%s\n", p->id, p->age, p->name);
	printf("(*p).id=%d, (*p).age=%d, (*p).name=%s", (*p).id, (*p).age, (*p).name);
	
	free(p);
	p = NULL;
	
	return 0;
}
输出结果
p->id=1, p->age=20, p->namecdtaogang
(*p).id=1, (*p).age=20, (*p).name=cdtaogang

在这里插入图片描述

7.3 结构体套一级指针

示例1:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


struct std
{
    
    	
	int age;
	char* name; //一级指针
};

int main() 
{
    
    
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 18;
	p->name = "cdtaogang";

	printf("%d %s\n", p->age, p->name);

	return 0;
}

在这里插入图片描述

输出结果
18 cdtaogang

示例2:

struct std
{
    
    	
	int age;
	char* name; //一级指针
};

int main() 
{
    
    
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 18;
	//p->name = "cdtaogang";
	strcpy(p->name, "cdtaogang"); // error 野指针 p没有指向 相当于 char *name; strcpy(name, "cdtaogang")一个道理

	printf("%d %s\n", p->age, p->name);

	return 0;
}

在这里插入图片描述

在这里插入图片描述

示例3:

struct std
{
    
    	
	int age;
	char* name; //一级指针
};

int main() 
{
    
    
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 18;
	//p->name = "cdtaogang"; // ok
	p->name = (char*)malloc(128);
	strcpy(p->name, "cdtaogang"); // error 野指针 p没有指向

	printf("%d %s\n", p->age, p->name);

	return 0;
}

在这里插入图片描述

输出结果
18 cdtaogang

示例4:简化分析p->name = "cdtaogang";strcpy(p->name, "cdtaogang");两种方式,这里的name在以下示例以p来表示

// 正确示例
int main()
{
    
    
	char* p;
	p = "cdtaogang";
}

在这里插入图片描述

// 错误示例
int main()
{
    
    
	int* p;
	strcpy(p, "cdtaogang");// 将cdtaogang的内容拷贝到p所指向的空间(地址)
}

在这里插入图片描述

// 正确示例
int main()
{
    
    
	char* p;
	p = (int*)malloc(128);
	strcpy(p, "cdtaogang");// 将cdtaogang的内容拷贝到p所指向的空间(地址)
}

在这里插入图片描述

示例5:结构体套结构体一级指针

struct s
{
    
    
	int a;
};
struct std
{
    
    	
	int age;
	char* name; //一级指针
	struct s* num; // 指针需要申请开辟空间
	//struct s num2; // 变量不需要申请开辟空间
};

int main()
{
    
    
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 20;

	p->name = (char*)malloc(128);
	strcpy(p->name, "cdtaogang");
	//p->num2.a = 100;  // num2是变量用.不能用->
	p->num->a = 200; // error  num是野指针,不能直接赋值给num所指向的空间

	printf("%d %s\n", p->age, p->name);

	return 0;
}

在这里插入图片描述

解决方法一样申请开辟空间即可

struct s
{
    
    
	int a;
};
struct std
{
    
    	
	int age;
	char* name; //一级指针
	struct s* num; // 指针需要申请开辟空间
	//struct s num2; // 变量不需要申请开辟空间
};

int main()
{
    
    
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 20;

	p->name = (char*)malloc(128);
	strcpy(p->name, "cdtaogang");
	//p->num2.a = 100;  // num2是变量用.不能用->
	//p->num->a = 200; // error  num是野指针,不能直接赋值给num所指向的空间
	p->num = (struct s*)malloc(sizeof(struct s));
	p->num->a = 200;

	printf("%d %s %d\n", p->age, p->name, p->num->a);

	return 0;
}

在这里插入图片描述

释放空间,从里往外释放,有多少个malloc就释放free多少个(p的空间是定义的时候就有的 ,而p指向的空间是malloc之后才有的,即才有了age、name、num的空间而name和num指向的空间是malloc之后才有的

int main()
{
    
    
	struct std* p = (struct std*)malloc(sizeof(struct std));
	p->age = 20;

	p->name = (char*)malloc(128);
	strcpy(p->name, "cdtaogang");
	//p->num2.a = 100;  // num2是变量用.不能用->
	//p->num->a = 200; // error  num是野指针,不能直接赋值给num所指向的空间
	p->num = (struct s*)malloc(sizeof(struct s));
	p->num->a = 200;

	printf("%d %s %d\n", p->age, p->name, p->num->a);

	free(p->name);
	free(p->num);
	free(p);

	return 0;
}

在这里插入图片描述

8) 结构体做函数参数*

8.1 结构体普通变量做函数参数

示例:结构体普通变量做函数参数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <string.h>

//结构体类型的定义
struct stu
{
    
    
	char name[50];
	int age;
};

//函数参数为结构体普通变量
void set_stu(struct stu tmp)
{
    
    
	strcpy(tmp.name, "cdtaogang");
	tmp.age = 18;
	printf("tmp.name = [%s], tmp.age = [%d]\n", tmp.name, tmp.age);
}

int main()
{
    
    
	struct stu s = {
    
     0 };
	set_stu(s); //值传递
	printf("s.name = [%s], s.age = [%d]\n", s.name, s.age);

	return 0;
输出结果
tmp.name = [cdtaogang], tmp.age = [18]
s.name = [], s.age = [0]

8.2 结构体指针变量做函数参数

示例:结构体指针变量做函数参数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <string.h>

//结构体类型的定义
struct stu
{
    
    
	char name[50];
	int age;
};

//函数参数为结构体指针变量
void set_stu_pro(struct stu* tmp)
{
    
    
	strcpy(tmp->name, "cdtaogang");
	tmp->age = 18;
	printf("tmp->name = [%s], tmp->age = [%d]\n", tmp->name, tmp->age);
}

int main()
{
    
    
	struct stu s = {
    
     0 };
	set_stu_pro(&s); //地址传递
	printf("s.name = [%s], s.age = [%d]\n", s.name, s.age);

	return 0;
}
输出结果
tmp->name = [cdtaogang], tmp->age = [18]
s.name = [cdtaogang], s.age = [18]

8.3 结构体数组名做函数参数

示例:结构体数组名做函数参数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include <string.h>


struct stu
{
    
    
	
	int id;
	char name[128];

};
//void set_tmp(struct stu tmp[5], int n)
void set_tmp(struct stu *p, int n)
{
    
    
	for (int i = 0; i < n; i++)
	{
    
    	
		// 第一种方式用点域
		(*(p + i)).id = 22;
		p[i].id = 22; // 上面的简写
		// 第二种方式用指向
		//(p + i)->id = 22;
		char buf[128];
		sprintf(buf, "%s%d", "cdtaoang", i+1);
		strcpy(p[i].name, buf);
		printf("p[%d].id = %d, p[%d].name = %s\n", i, p[i].id, i, p[i].name);
	}
}

int main()
{
    
    

	struct stu tmp[5] = {
    
     0 };
	int n = sizeof(tmp) / sizeof(tmp[0]);
	set_tmp(tmp, n); // tmp = &tmp[0]
	printf("\n");
	for (int i = 0; i < n; i++)
	{
    
    
		printf("tmp[%d].id = %d, tmp[%d].name = %s\n", i, tmp[i].id, i, tmp[i].name);
	}

	return 0;
}

在这里插入图片描述

在这里插入图片描述

8.4 const修饰结构体指针形参变量

示例:const修饰结构体指针形参变量

#include<stdio.h>


struct stu
{
    
    
	int id;
	char name[128];
};

int main()
{
    
    
	struct stu a;
	struct stu b;
	struct stu const *p = &a;
	// p->id = 10; // error  const修饰的是*,不能通过指针p去修改p指向的那块空间里面内容(指向)

	struct stu * const p2 = &a;
	p2->id = 20; // ok
	//p2 = &b; // error const修饰的是指针变量p, 不能修改变量p本身的内容(指向)

	return 0;
}

共用体(联合体)

  • 联合union是一个能在同一个存储空间存储不同类型数据的类型;
  • 联合体所占的内存长度等于其最长成员的长度倍数,也有叫做共用体;
  • 同一内存段可以用来存放几种不同类型的成员,但每一瞬时只有一种起作用;
  • 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖;
  • 共用体变量的地址和它的各成员的地址都是同一地址。

1) 共用体的定义和初始化

示例1:定义一个共用体数据类型

union test
{
    
    
	char a;
	short b;
	int c;
};

示例2:定义共用体变量,跟结构体定义方式一样

union test
{
    
    
	char a;
	short b;
	int c;
}tmp;
union test
{
    
    
	char a;
	short b;
	int c;
};
union test tmp;
union
{
    
    
	char a;
	short b;
	int c;
}tmp;

示例3:共用体变量的初始化(共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖

#include <stdio.h>


union test
{
    
    
	char a;
	short b;
	int c;
};

int main()
{
    
    	
	union test tmp;
	tmp.a = 0x01;
	tmp.b = 0x0a0b;
	tmp.c = 0x01020304;
	
	printf("tmp.a = %x\n", tmp.a); // 04
	printf("tmp.b = %x\n", tmp.b); // 0304
	printf("tmp.c = %x\n", tmp.c); // 01020304

	return 0;
}

在这里插入图片描述

#include <stdio.h>


union test
{
    
    
	char a;
	short b;
	int c;
};

int main()
{
    
    	
	union test tmp;
	tmp.a = 0x01;
	tmp.c = 0x01020304;
	tmp.b = 0x0a0b;
	
	printf("tmp.a = %x\n", tmp.a); // 0b
	printf("tmp.b = %x\n", tmp.b); // 0a0b
	printf("tmp.c = %x\n", tmp.c); // 01020a0b

	return 0;
}

在这里插入图片描述
示例4:共用体的大小

printf("sizeof(tmp)=%d", sizeof(tmp));  //sizeof(tmp)=4 即 sizeof(int)=4 联合体所占的内存长度等于其最长成员的长度倍数

2) 共用体判断大小端

小端: 低位存低地址,高位存高地址(大型服务器)
大端: 低位存高地址,高位存低地址(小型计算机)

在这里插入图片描述

示例:共用体判断大小端

#include <stdio.h>


union test
{
    
    
	short b;
	char buf[2];
};

int main()
{
    
    
	union test tmp;
	tmp.b = 0x0102;

	if (tmp.buf[0] == 0x01)
	{
    
    
		printf("大端\n");
	}
	else
	{
    
    
		printf("小端\n");
	}

	return 0;
}

在这里插入图片描述

输出结果
小端

枚举

枚举: 将枚举类型的变量的值一一列举出来,变量的值只限于列举出来的值的范围内。

枚举类型定义:

enum  枚举名
{
    
    
	枚举值表
};
  • 在枚举值表中应列出所有可用值,也称为枚举元素。
  • 枚举值是常量,不能在程序中用赋值语句再对它赋值。
  • 举元素本身由系统定义了一个表示序号的数值从0开始顺序定义为0,1,2 …

1) 枚举定义

示例1:为了避免需要多次定义宏,C语言提供了枚举

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#define Mon 1
#define Tue 2
#define Wed 3


int main()
{
    
    	
	int num;
	scanf("%d", &num);

	if (Mon == num)
	{
    
    
		printf("游泳\n");
	}
	else if (Tue == num)
	{
    
    
		printf("跑步\n");
	}
	else if (Wed == num)
	{
    
    
		printf("游戏\n");
	}


	return 0;
}
// 枚举定义
// 默认枚举里面的值从0开始
enum week
{
    
    
	Mon,
	Tue,
	Wed
};

int main()
{
    
    	
	printf("%d %d %d", Mon, Tue, Wed); // 0 1 2
	return 0;
}

2) 枚举赋值

示例2:枚举赋值

enum week
{
    
    
	Mon=1,
	Tue,
	Wed
};

int main()
{
    
    	
	printf("%d %d %d", Mon, Tue, Wed); // 1 2 3
	return 0;
}
enum week
{
    
    
	Mon,
	Tue=5,
	Wed
};

int main()
{
    
    	
	printf("%d %d %d", Mon, Tue, Wed); // 0 5 6
	return 0;
}

3) 定义枚举变量

示例1:先定义枚举类型,再定义枚举变量

enum week
{
    
    
	Mon,
	Tue=5,
	Wed
};

int main()
{
    
    	
	enum week day = Wed; //给枚举变量 day 赋值,值就是Wed枚举元素
	printf("%d %d %d", Mon, Tue, Wed); // 0 5 6
	return 0;
}

示例2:定义枚举类型的同时定义枚举变量

enum week
{
    
    
	Mon,
	Tue=5,
	Wed
}day;// 表示 定义了一个枚举类型 enum week,同时定义了一个变量 day(类型是 enum week)

int main()
{
    
    	
	day = Wed; //给枚举变量 day 赋值,值就是某个枚举元素
	printf("%d %d %d", Mon, Tue, Wed); // 0 5 6
	return 0;
}

示例3:省略枚举名称,直接定义枚举变量

```c
enum
{
    
    
	Mon,
	Tue=5,
	Wed
}day;//这样使用枚举,该枚举类型只能使用一次

案例:使用枚举实现#define false 0 #define true 1

#include <stdio.h>

enum weekday
{
    
    
	sun = 2, mon, tue, wed, thu, fri, sat
} ;

enum bool
{
    
    
	flase, true
};

int main()
{
    
    	
	// 先定义枚举类型,再定义枚举变量
	enum weekday a, b, c;
	a = sun;
	b = mon;
	c = tue;
	printf("%d,%d,%d\n", a, b, c);

	enum bool flag;
	flag = true;

	if (flag == 1)
	{
    
    
		printf("flag为真\n");
	}
	return 0;
}

在这里插入图片描述

typedef

typedefC语言的关键字,作用是为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型

  • #define不同,typedef仅限于数据类型,而不是能是表达式或具体的值
  • #define发生在预处理,typedef发生在编译阶段

示例1:使用typedef起别名

#include <stdio.h>


typedef int u32;

struct stu
{
    
    
	int id;
	int age;
};
typedef struct stu ST;
int main()
{
    
    
	int a = 10;
	u32 b = 10;
	ST tmp;
	tmp.id = 2;
	tmp.age = 20;
	printf("%d %d\n", sizeof(a), sizeof(b));
	printf("%d %d\n", tmp.id, tmp.age);

	return 0;
}
输出结果
4 4
2 20

示例2:宏与typedef起别名

#include <stdio.h>
#define CHAR char
typedef char CHAR32;

int main()
{
    
    
	CHAR a;
	CHAR32 b;

	a = 10;
	b = 20;
	printf("%d %d\n", sizeof(a), sizeof(b));

	return 0;
}
输出结果
1 1

示例3:使用宏起别名存在的问题和风险

#include <stdio.h>
#define CHAR char*
typedef char* CHAR32;

int main()
{
    
    
	CHAR x, y;  // char *x,y;
	CHAR32 j, k; // char *j,*k;
	printf("%d %d\n", sizeof(x), sizeof(y));
	printf("%d %d\n", sizeof(j), sizeof(k));

	return 0;
}
输出结果
4 1
4 4

在实际编程中,取别名广泛应用,如下图所示查看VS编译器中size_t类型其实就是int类型

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41782425/article/details/128010399