一步一步写算法(关于malloc函数)

v 接着上一次的自我实现字符串拷贝函数,其实我们在刚开始的main函数中也可以将char a[10] = {0};char b[10] = {0};定义为两个指针char *a,*b;指针是指向地址的,同样应该可以用于my_copy(a,b);这个函数里面的地址传递。那么,我们来试一下,可不可以将char a[10] = {0};char b[10] = {0};直接换为char *a,*b;来实现我们的字符串拷贝函数呢?

 

 

下面是进行尝试的函数:

#include <stdio.h>

void my_copy(char *i,char *j)
{
	while(*i++ = *j++);     //简练:同时实现取值,赋值,地址加一,三个功能 
}


int main()
{
	//char a[10] = {0};
	//char b[10] = {0};
	char *a,*b;

	printf("Please input the string of b:\n");
	scanf("%s",b);

	my_copy(a,b);
	printf("a : %s\n",a);

	return 0;
}


运行结果:

gcc编译环境下,在输入字符串后,终端上报出了段错误。

 

这是上面原因呢?

首先,段错误发生错误的原因是访问不该访问的内存空间。那么,也就是我们上述的程序中,有变量访问了不该访问的内存空间。

而我们刚刚只是修改了一下 char *a,*b;问题是出在这两个变量上。就变量所占的内存空间,我们来分析一下。其中,char *a,*b;a,b变量只是指向地址,却没有确定的指向方向。这样操作是不合法的,因为在操作系统分配的虚拟内存当中,有些内存空间是我们开发人员无法进行操作的。所以,以上的地址指向不明,因而造成了段错误。(关于内存空间,我下面将另外用一篇博客来说明)

 

v 为了获得一段合理的内存,我们使用malloc函数。malloc函数的作用是在堆上开辟一段内存。虚拟内存中的堆的特点是:其空间由开发人员管理,空间的开辟和释放也是由开发人员完成。所以,我们可以通过malloc函数来为a,b变量在堆上开辟一段空间。

 

v 下面是单独写的一个函数来实现的为a,b变量在堆上开辟一段空间

 

 

v 程序示例:

#include <stdio.h>
#include <stdlib.h>

void my_copy(char *i,char *j)
{
	while(*i++ = *j++);
}



void *memory_init(char *p)
{
	p = (char *)malloc(sizeof(char)*10);
}


int main()
{
	char *a,*b;
	memory_init(a);
	memory_init(b);

	printf("Please input the string of b:\n");
	scanf("%s",b);

	my_copy(a,b);
	printf("a : %s\n",a);

	return 0;
}



运行结果:

当我们在输入字符串后,终端上又显示了段错误。

 

这是为什么呢?我们不是已经利用malloc函数为两个变量在堆上开辟了空间。为什么还是显示段错误呢?

 

v 下面我们利用例子来讲一下原因:假设原来指针变量a指向的空间是0x100,指针变量b指向的空间是0x200。在调用函数memory_init(a);函数后,a传地址0x100p,然后利用malloc函数为p在堆上开辟了一段空间,假设在堆上开辟的空间首地址是0x500。但是在函数执行完后,形参P将释放空间,那么p里面保存的0x500也将会释放。最后,也就是相当于a的地址还是0x100,我们想要实现的为a开辟空间并没有实现。

 

v 如果想要解决这个问题,可以使用一个return 语句,来返回我们在堆上所开辟空间的地址。

v 程序示例:

#include <stdio.h>
#include <stdlib.h>

void my_copy(char *i,char *j)
{
	while(*i++ = *j++);
}



char *memory_init()
{
	return (char *)malloc(sizeof(char)*10);
}


int main()
{
	char *a,*b;
	a = memory_init();
	b = memory_init();

	printf("Please input the string of b:\n");
	scanf("%s",b);

	my_copy(a,b);
	printf("a : %s\n",a);

	return 0;
}

运行结果:

Please input the string of b:

hello

a : hello

 

由此,运行结果正确。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值