结构体:
自定义的结构,类型。
struct <类名>
{
};
typedef 取别名。
变量:定义 赋值(初始化) 引用
数组:定义 赋值(初始化) 引用
内存四区:
1.数据区
a.常量区:存放常量
b.全局区/静态区:用于存放全局变量和静态变量以及常量,程序结束后系统自动释放。
2.代码区:存放程序的二进制代码。
3.栈区:系统来操控的,编译器自动分配释放,存放函数形参局部变量等。
4.堆区:手动分配释放(动态内存申请与释放),若不释放结束时可由操作系统回收。
动态内存分配:
#include <stdlib.h> || #include <malloc.h>
void *malloc(unsigned int size);
Window下原型
extern void *malloc(unsigned int num_bytes);
malloc开辟内存(用于申请一块连续的指定大小的内存区域),以void*类型返回分配的内存地址。
malloc为函数而new是c++关键字,本身不是函数,不依赖头文件,且new可以返回指定类型的指针,并能够自动计算所需大小。
int *p = NULL;//int *p; p=new int; p = (int*)malloc(sizeof(int));//需要强制类型转换为实际类型的指针 if (p == NULL) { printf("动态内存开辟失败! "); } *p = 5; printf("%d ", *p);
ps:开辟的内存如果不用了一定要释放。
free()函数声明:
void free(void *ptr);
释放动态内存分配地址(把之前申请的还给系统)
free(p);
delete运算符
是对应new运算符的,使用方法基本与free相同。
顺序表(数组):
动态数组:
一维:
int *p = (int*)malloc(sizeof(int)* 10);
free(p);
二维:
int**p = (int **)malloc(sizeof(int*)* 3); for (int i = 0; i < 3; i++) { p[i] = (int *)malloc(sizeof(int)* 5); } for(int i=0;i<3;i++) { free(p[i]);//由内向外全部释放 } free(p);
其他的跟普通的数组操作一样。
例:
释放之后不被控制
realloc函数
原型是extern void *realloc(void *mem_address, unsigned int newsize);更改已经配置的内存空间,即更改由malloc()函数分配的内存空间的大小。
链表:链式结构(注意链表和数组不一样,内存的存放是无序的)
数据域:存放需要的有用的数据
指针域:用来连接各个节点,形成连式结构的指针。
节点:每一个单独数据内存空间叫做一个节点。
头指针:第一个节点的地址。
尾指针:最后一个节点的地址。
常见的链表有2种:
带空头节点的链表:头节点不存放数据,从头节点后面一个节点开始存放。
不带空头节点的链表:链表中每一个节点都用来存放数据。
带空头节点的链表:
以学生成绩管理系统增删查为例
//结构体 typedef struct Student //别名 { /*数据域*/ int number; char name[20]; float math; /*指针域*/ struct Student* pnext; }STU; typedef STU* Pt_Stu; //创建链表(链表的初始化) Pt_Stu ListInit() { //开辟空间 Pt_Stu plist = (Pt_Stu)malloc(sizeof(STU)); //填充数据 plist->pnext=NULL; return plist; } //在尾部增加,限制增加个数时可在主函数中使用for循环 void AddListNode(Pt_Stu plist) //plist为函数形参,不改变实参 { //开辟空间 Pt_Stu pnode = (Pt_Stu)malloc(sizeof(STU)); //填充数据 printf("input number:"); scanf("%d", &pnode->number); printf("input name:"); scanf("%s", pnode->name); printf("input score:"); scanf("%f", &pnode->math); pnode->pnext = NULL; //链接链表 //plist 移动到最后一个节点。 while (plist->pnext != NULL) { plist = plist->pnext; } plist ->pnext = pnode; } /*在头部增加 pnode->pnext = plist->pnext;//倒序 plist->pnext = pnode;*/ //遍历链表 全部输出 void TraverseList(Pt_Stu plist) { //plist指向第一个存放数据的节点 plist = plist->pnext; //遍历后输出所有信息 while (plist != NULL) { printf("number:%d name:%s score:%.2f ", plist->number, plist->name, plist->math); plist = plist->pnext; } } //查找链表 void SearchList(Pt_Stu plist,int num) { //plist指向第一个存放数据的节点 plist = plist->pnext; while (plist != NULL) { if (plist->number==num) //比较字符串使用 strcmp { printf("number:%d name:%s %.2f ", plist->number, plist->name, plist->math); } plist = plist->pnext; } //修改链表 void ReviseList(Pt_Stu plist, int num) { //plist指向第一个存放数据的节点 plist = plist->pnext; while (plist != NULL) { if (plist->number == num) { plist->math = 60; printf("number:%d name:%s %.2f ", plist->number, plist->name, plist->math); } plist = plist->pnext; } } //删除节点 void DeleteNode(Pt_Stu plist,int number) { Pt_Stu p = plist->pnext; //创建指针 Pt_Stu p1 = plist; //操纵两个指针一前一后 while (p != NULL) { if (p->number == number) { p1->pnext = p->pnext; free(p); // 删掉一个 p = p1->pnext; } else { p = p->pnext; p1 = p1->pnext; } } }