1、函数指针
2、函数指针-案例
3、动态分配内存
4、重新分配内存
5、内存泄漏
1、函数指针
//允许使用过时的函数和不安全的函数,去掉警告
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
//1、函数指针
void showMessage(){
//弹窗
MessageBox(0, "消息内容", "消息标题", 0);
}
double add(double a, double b){
return a + b;
}
void add(int a, double b){
}
void main(){
//传统的写法
//直接调用
//showMessage();
//采用函数指针的方式调用
//void(*p)() = showMessage;
//p();
//间接调用
//带返回值和参数列表的函数指针
double(*p1)(double a, double b) = add;
double d = p1(2, 3);
printf("%lf", d);
//补充:函数指针-不仅仅是地址,必须明确的指定函数的指针类型,以及返回值和参数列表
//回想Java语言:方法重载(方法名相同,参数列表不同,或者参数类型不同)
getchar();
}
2、函数指针-案例
//2、函数指针-案例
//函数的返回值是一个指针,函数的参数列表是一个数组,返回数组的最小值
int* getMin(int a[], int len){
//printf("getMin地址:%#x\n", &a);
//int len = sizeof(a) / sizeof(int);
int i = 0;
//选择法进行判断筛选
//首选:假设数组中第一个元素是最小值
int min = a[0];
int *p = &a[0];
for (; i < len; i++){
if (a[i] < min){
min = a[i];
p = &a[i];
}
}
return p;
}
void main(){
int a[5];
// 我要让每一次都不一样
// 初始化随机数发生器
//time_t实际上就是一个时间---长整型
time_t t;
//srand传入的参数与不相同,那么就会生成新的随机数(随机数种子)
//time:1970年1月1日0分0秒
srand((unsigned)time(&t));
int i = 0;
for (; i < 5; i++){
a[i] = rand() % 50;
printf("%d\n", a[i]);
}
printf("main地址:%#x\n", &a);
//计算数组的长度
int len = sizeof(a) / sizeof(int);
int* min = getMin(a, len);
printf("最小值:%d", *min);
getchar();
}
3、动态分配内存
//3、动态分配内存
void main(){
//40MB
//报错了:Stackoverflow栈溢出异常,数组的数据默认保存在栈内存中
//C语言中:内存分配
//1、栈区:自动分配自动释放(存放的内容:主要存放的是函数的参数值,局部变量)--更高效
//2、堆区:需要自己回收释放
//3、全局区和静态区 全局变量和静态变量(系统自动管理,当我们的应用程序结束的时候释放)
//4、程序代码区
//5、字符常量区 常量字符串(系统自动管理,当我们的应用程序结束的时候释放)
//OC语言
//以下特性:在xcode4.0
//1、栈区:自动分配自动释放(存放的内容:主要存放的是函数的参数值,局部变量)--更高效
//2、堆区:需要自己回收释放
// xcode 4.0之后:ARC自动引用计数(类似于Java GC)
int a[1024 * 1024 * 10];
getchar();
//补充:Stackoverflow栈溢出异常
//栈区内存的大小:操作系统和C库版本相关(大小是有限制的)
//栈: 先进后出
//队列:先进先出
}
//栈区
void stackMethod(){
int a[5];
printf("%#x\n", a);
int i = 0;
for (; i < 5; i++){
a[i] = i + 1;
}
printf("\n");
}
void main(){
//循环创建数组
while (1)
{
stackMethod();
Sleep(5000);
}
}
//堆区:在堆区开辟内存空间
//malloc:开辟一块新的内存空间
void heapMethod(){
//在堆区开辟了一块40M的内存空间
int* p = (int*)malloc(1024 * 1024 * 10 * 4);
printf("\n");
}
void main(){
//循环创建数组
while (1)
{
heapMethod();
Sleep(6000);
}
}
//回收内存--堆区
void heapMethod(){
//在堆区开辟了一块40M的内存空间
int* p = (int*)malloc(1024 * 1024 * 10 * 4);
//回收内存
free(p);
printf("\n");
}
void main(){
//循环创建数组
while (1)
{
heapMethod();
Sleep(6000);
}
}
//创建一个数组,动态的指定数组的大小(动态分配数组大小)
void main(){
int len;
printf("请输入数组的长度:");
scanf("%d", &len);
//动态指定数组的大小(用于存储int类型的数据)
//注意:malloc返回void*
//在C语言void*方法指针可以指向任何类型的方法指针
//回想Java Object类型
//p就是首地址
int* p = (int*)malloc(5 * sizeof(int));
//double* p = (double*)malloc(len * sizeof(int));
//char* p = (char*)malloc(len * sizeof(int));
int i = 0;
for (; i < len; i++){
p[i] = rand() % 50;
printf("%d %#x\n", p[i], &p[i]);
}
//C语言当中,动态分配
//联想到:java集合
system("pause");
}
4、重新分配内存
//重新分配内存
//calloc
void main(){
int len;
printf("请输入数组的长度:");
scanf("%d", &len);
//int* p = (int*)malloc(5 * sizeof(int));
//第一个参数:数组长度
//第二个参数:每个元素大小
//更方便
int* p = (int*)calloc(5, sizeof(int));
int i = 0;
for (; i < len; i++){
p[i] = rand() % 50;
printf("%d %#x\n", p[i], &p[i]);
}
//改变原始内存区域的大小(增加-减小)
int addLen;
printf("请输入数组的增加长度:");
scanf("%d", &addLen);
//重新输出数组的数据---需要从新分配内存
//注意:新的=老的+增加的
//realloc更改已经配置的内存空间
//缩小:会导致一部分数据丢失
//扩大(连续不断-线性排列)
//情况一:如果当前的内存段后面有需要的内存空间,就会直接追加(注意:返回原指针)
//情况二:如果当前内存段后面空闲的字节空间不够
//那么就会重新再堆内存中寻找能够容纳该数据大小的内存区域(注意:返回值新的内存地址,原来的被释放)
//情况三:如果没有容身之处,申请内存失败,将返回NULL,而且原来的指针有效
int* p1 = (int*)realloc(p, sizeof(int)*(len + addLen));
i = len;
for (; i < len + addLen; i++){
p1[i] = rand() % 50;
}
//输出
i = 0;
for (; i < len + addLen; i++){
printf("%d %#x\n", p1[i], &p1[i]);
}
system("pause");
}
//内存分配注意事项:
//1、不能够多次释放内存
//2、释放内存之后,给原来的指针设置NULL
//3、内存泄漏
void main(){
int len;
printf("请输入数组的长度:");
scanf("%d", &len);
int* p = (int*)calloc(5, sizeof(int));
int i = 0;
for (; i < len; i++){
p[i] = rand() % 50;
printf("%d %#x\n", p[i], &p[i]);
}
//释放内存
free(p);
//标记内存已经被释放
p = NULL;
free(p);
system("pause");
}
5、内存泄漏
//以下情况导致内存泄漏
void heapMethod(){
//在堆区开辟了一块40M的内存空间
int* p = (int*)malloc(1024 * 1024 * 10 * 4);
p = NULL;
//回收内存
free(p);
printf("\n");
}
void main(){
//循环创建数组
while (1)
{
heapMethod();
Sleep(6000);
}
}