C语言-函数指针+动态内存分配

//允许使用过时的函数和不安全的函数,去掉警告
#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、函数指针-案例
//函数的返回值是一个指针,函数的参数列表是一个数组,返回数组的最小值
/*
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、动态分配内存
/*
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");
}
*/

//重新分配内存
//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");
}
*/



//以下情况导致内存泄漏
void heapMethod(){
	//在堆区开辟了一块40M的内存空间
	int* p = (int*)malloc(1024 * 1024 * 10 * 4);

	p = NULL;

	//回收内存
	free(p);
	printf("\n");
}

void main(){
	//循环创建数组
	while (1)
	{
		heapMethod();
		Sleep(6000);
	}
}


如果出现了以下错误:可以用#define _CRT_SECURE_NO_WARNINGS来解决

错误	1	error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.	e:\android-tools\project\ndk-lesson\ndk_c语言_函数指针_动态内存分配\ndk_c语言_函数指针_动态内存分配\源.c	187	1	NDK_C语言_函数指针_动态内存分配


整理自代码

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值