枚举
- 枚举:C语言中一种自定义数据类型。
- 语法:
- enum :使用enum关键字来定义, enum 枚举名称 { 枚举元素1, 枚举元素2 , ... 枚举元素n};
- 枚举常量:枚举元素也称为枚举成员或枚举常量。
- 枚举元素的值必须在同一枚举中是唯一的。
- 枚举元素的值必须是整数类型,通常int。
- 如果没有为枚举元素指定值,编译器会自动为他们分配值,从 0 开始。
- 也可以自定义值,需保证唯一性和整型类型。
- 枚举变量:定义变量时指定类型是我们所定义的枚举类型,该变量称为枚举变量。枚举变量的值应该是枚举类型中的枚举常量中的一个。
- 定义枚举变量的语法:
- 先定义枚举类型,在定义枚举变量。
- 定义枚举类型的同时声明枚举变量。
- 定义枚举类型的同时声明枚举变量,且省略枚举名称。
- 遍历枚举时,枚举常量的值应该是连续的。
#include <stdio.h>
// 定义枚举
enum Week {
MONDAY = 1,
TUESDAY,
WEDNESDAY,
THRUDAY,
FRIDAY,
SATURDAY,
SUNDAY
};
int main() {
enum Week week;
printf("请你输入数字:");
scanf("%d", &week);
// for (int day = 0; day < week; day++) {
// printf("今天是星期%d\n", day);
// }
switch (week) {
case MONDAY:
printf("星期一\n");
break;
case TUESDAY:
printf("星期二\n");
break;
case WEDNESDAY:
printf("星期三\n");
break;
case THRUDAY:
printf("星期四\n");
break;
case FRIDAY:
printf("星期五\n");
break;
case SATURDAY:
printf("星期六\n");
break;
case SUNDAY:
printf("星期日\n");
break;
default:
printf("输入有误\n");
break;
}
for (int i = MONDAY; i <= SUNDAY; i++) {
printf("%d\n", i);
}
return 0;
}
结构体
- 结构体:struct 关键字,将不同的类型的值组合在一起。类似与对象和类的功能。
- 声明结构体格式:
-
struct 结构体名 { 数据类型1 成员名1; 数据类型2 成员名2; ... 数据类型n 成员名n; };
结构体一般格式
-
结构体变量
-
先定义结构体,在创建结构体变量。
-
在定义结构体的同时定义结构体变量。
-
在定义时也可以省略结构体名。
-
结构体是一种自定义的数据类型,结构体变量是根据结构体类型创建的变量,用于存储数据。
-
-
成语的获取和赋值:结构体使用 点号 . ,获取单个成员,进行赋值和取值。
-
结构体指针:指向结构体的指针变量。
-
语法: struct 结构体名 *结构体指针变量名;
-
声明结构体指针:先定义一个结构体变量,在创建结构体指针,取其地址作为结构体指针的值。
-
结构体指针访问成员: 通过 -> 操作符范文结构体的成员。
-
-
指针变量p指向一个结构体变量stu,以下3中用法等价:
-
stu.成员名
-
(*p).成员名
-
p->成员名
-
总结:
结构体是自定义的数据类型,表示一种数据类型;结构体变量代表一个具体变量。
#include <stdio.h>
// 定义结构体
struct Students {
int id;
char *name;
char *genter;
char *email;
char *phone;
};
// 定义同时声明结构体变量
// struct Students
// {
// int id;
// char *name;
// char *genter;
// char *email;
// char *phone;
// } students;
// 省略结构体名
// struct
// {
// int id;
// char *name;
// char *genter;
// char *email;
// char *phone;
// } students;
int main() {
// 定义结构体变量
struct Students stu;
// 结构体成员赋值
stu.id = 101;
stu.name = "咸亨";
stu.genter = "男";
stu.email = "123@163.com";
stu.phone = "13895647854";
printf("stu 的 id %d, stu 的 name %s\n", stu.id, stu.name);
// 结构体指针
struct Students stu1 = {102, "tom", "女", "124424@123.com", "18695456889"};
struct Students *ptr = &stu1;
// 访问
ptr->name = "LIHua";
printf("ptr->name = %s\n", ptr->name);
(*ptr).phone = "12345678";
printf("ptr->phone = %s\n",(*ptr).phone);
return 0;
}
#include <string.h> strcmp(a, b); 比较连个字符串是否相等,相等等于0, 不等等于 -1;
“hello” == "hello" ——C语言判断时 当成字面量-》常量,存储在只读数据段中,存储地址是相同的。
共用体
- 共用体:union关键字,自定义数据结构。内部可以包含各种属性,但同一时间只能有一个属性。
- 结构体变量所占内存长度是各成员内存的长度的叠加,共用体变量所占内存长度等于最长的成员的长度,吉特成员共用一个内存区。
- 声明结构体:
union 共用体类型名称 {
数据类型1 成员名1;
数据类型2 成员名2;
...
数据类型n 成员名n;
};
共用体:同一时间只能取到一个属性,最后赋值的属性,覆盖前面的属性值。
- 声明公用体变量的方式:
- 先定义共用体类型,在定义共用体变量;
- 定义共用体类型的同时定义共用体变量;
- 在定义时可以不给出共用体名。
- 成员的获取和赋值
- union data a; a.c = 4;
- 声明共用体变量的同时,给任一成员赋值:union data a = { .c = 2};
- 声明共用体变量的同时,给首成员赋值。union data a = { 8 };
- 不指定成员名,所以只能为第一个成员赋值。
#include <stdio.h>
int main() {
// 共用体
// union data {
// int a;
// char b;
// double c;
// } st, wu;
// union {
// int a;
// char b;
// } st, wu;
union data {
int a;
char b;
double c;
};
// union data st, wu;
// st.a = 10;
// union data st = {.b = 20};
union data st = { 30}; // 赋值给第一个 ,但是公用一个 内存地址,访问都是 30
printf("%d\n", st.a);
// printf("%d\n", st.b);
// printf("%d\n", st.c);
return 0;
}
typedef
- tepydef:为一个数据类型起一个新的别名。
- typedef声明数组类型、指针类型、结构体类型、共用体类型等。
- 通常typedef声明的类型名的第一个字母大写,以便和系统的区分。
- 为某个基本类型起别名:typedef 类型名 别名;也可以一次起多个别名;
- 为结构体、共用体起别名;typedef struct Treenode Tree; 别名 Tree。
- 为指针起别名;typedef char *String;
- 为数组起别名;typedef int Num[100]; 别名 Num;
动态内存分配
-
动态内存分配指根据需要
向系统申请
所需大小的空间,由于未在声明部分定义其为变量或者数组,不能通过变量名或者数组名来引用这些数据,只能通过指针来引用); -
指针:C99允许定义一个类型为void的指针变量,它可以指向任何类型的数据。
-
void指针:指针变量必须有类型,还不确定会有什么类型的数据写入内存,需要要先获得内存块,稍后再确定写入的数据类型,可以使用void指针。
- void 指针与其他所有类型指针之间是
互相转换关系
,任一类型的指针都可以转为 void 指针,而 void 指针也可以转为任一类型的指针。 - 由于不知道 void 指针指向什么类型的值,所以不能用 * 运算符取出它指向的值(解引用)。
#include <stdio.h>
int main()
{
int a = 110;
double b = 3.14;
// void *类型指针,可以与其他类型的指针相互转换
// 将右侧int *类型地址,隐式转换为void *
void *ptr = &a;
// 将右侧double *类型的地址,隐式转换为void*
void *ptr1 = &b;
// 无类型指针不能取值
// printf("%d\n", *ptr);
// void * 类型指针 强转其他类型
int *p = (int *)ptr;
double *p1 = (double *)ptr1;
printf("%d %lf\n", *p, *p1);
return 0;
}
- 其他类型指针赋给 void指针,使用隐式转换即可,void 指针赋给其他类型指针,建议使用显式类型转换。
- malloc() 函数:malloc() 函数用于分配一块连续的内存空间。
-
函数原型:void *malloc(size_t size);
返回值说明:
如果内存分配成功,返回一个void指针,指向新分配内存块的地址;如果分配失败(例如内存不足),返回一个空指针(NULL)。
参数说明:
size是要分配的内存块的大小,以字节为单位。
#include <stdio.h>
// 动态分类内存函数malloc,位于stdlib这个头文件当中
#include <stdlib.h>
int main()
{
// 在堆空间开了一个四字节内存大小
int *ptr = (int *)malloc(sizeof(int) * 1000);
// 每次用之前先判断申请内存是否充足
if (ptr == NULL)
{
printf("内存不足!!!!");
// 程序结束
return 1;
}
// 向申请哪个区域存储一个整数100
*ptr = 100;
printf("%d\n", *ptr);
// 每一次操作完以后,释放内存
free(ptr);
// //释放以后不要在操作【访问|赋值这块内存啦】!!!
printf("%d\n", *ptr);
return 0;
}
-
calloc() 函数:用于分配内存并将其初始化为零,它在分配内存块时会自动将内存中的每个字节都设置为零。
函数原型:
void *calloc(size_t numElements, size_t sizeOfElement);
返回值说明:
如果内存分配成功,返回一个 void 指针,指向新分配内存块的地址;如果分配失败(例如内存不足),返回一个空指针(NULL)。
参数说明:numElements是要分配的元素的数量;sizeOfElement是每个元素的大小(以字节为单位)。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n = 5;
// 两个参数:元素个数 每个元素占用字节
int *array = (int *)calloc(n, sizeof(int));
if (array == NULL)
{
printf("申请失败");
return 1;
}
// 申请这块'地',地址信息
printf("%p\n", array);
for (int i = 0; i < n; i++)
{
array[i] = i * 20;
}
// 访问
for (int i = 0; i < n; i++)
{
printf("%d\n", array[i]);
}
free(array);
return 0;
}
-
realloc() 函数:用于重新分配malloc() 或calloc() 函数所获得的内存块的大小。
函数原型:
void* realloc(void *ptr, size_t size);
返回值说明:
返回一个指向重新分配内存块的指针。如果内存重新分配成功,返回的指针可能与原始指针相同,也可能不同;如果内存分配失败,
返回
返回一个空指针(NULL
)。如果在原内存块上进行缩减,通常返回的原先的地址。
参数说明:ptr是要重新分配的内存块的指针;size是新的内存块的大小(以字节为单位)。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int main()
{
// 申请一点空间
int *ptr = (int *)malloc(400);
// 判断一下
if (ptr == NULL)
{
printf("申请失败");
return 1;
}
// 成功开了400字节内存
printf("%d\n", _msize(ptr));
// 开辟空间不够--->800
ptr = realloc(ptr, 8000);
printf("%d\n", _msize(ptr));
free(ptr);
return 0;
}
-
free()函数:
如果动态分配的内存空间没有被正确释放,这种情况称为内存泄漏,内存泄漏会导致系统中的可用内存逐渐减少,直到耗尽系统可用的内存资源。
free() 函数用于释放动态分配的内存,以便将内存返回给操作系统,防止内存泄漏。
函数原型:
void free(void *ptr);
返回值说明:
没有有返回值。
参数说明:
ptr
是指向要释放的内存块的指针,ptr必须是malloc() 或calloc() 动态分配的内存块地址。注意:
-
分配的内存块一旦释放,就不应该再次操作已经释放的地址,也不应该再次使用 free() 对该地址释放第二次。
-
如果忘记调用free()函数,会导致无法访问未回收的内存块,构成内存泄漏。
-