一、写在前面

最近学数据结构打算重新学一遍c语言,c语言函数返回值不像是java一样,java在定义一个成员变量后给其赋值,直接返回还是能拿到他的值,c却不一样了,成员变量放在栈内存中,栈内存中的成员变量会在方法执行后会释放,所以在成员变量赋值后返回是拿不到数据的

二、栈中的成员变量

1.不能取得值1

例子

看看这个例子:

char * testJB()
{
	char a='H';
	return &a;
}
void main()
{
	char p=testJB();
	putchar(p);
}

这个打印的时候你会发现没看到想要的’H’

分析

当testJB执行完成后,a执行的栈内存区域将自动被释放,这时候再返回a的地址已经拿不到数据了

2.不能取得值2

例子
char * test()
{
	char arr[]="hello world";
	return arr;
}
void main()
{
	char *p=test();
	puts(p);
}

运行结果:乱码输出;

分析
char arr[]="hello world";

内存过程:
首先将“hello world” 放入常量区,然后再把其重常量区拷贝到arr的栈内存中,函数执行完成后,arr的栈内存被自动释放,返回的arr首地址也拿不到数据了;

二、堆内存

1.可以取得值1

例子
char * test()
{
	char *p = malloc(sizeof(char)*10);
	*p = "hello word";
	return p;
}
void main()
{
    char *p=test();
	puts(p);
	free(p);
}

运行结果:hello word;

分析:

malloc 函数是在堆内存中开辟一块空间,并且不会自动释放,需要用完后手动释放;
因此,当函数执行完成后,堆内存不被释放,返回首地址仍然可以取得数据,注意用完后手动释放;

2.不可取得值1

例子
void test(char *num)
{
	num = malloc(sizeof(char) * 10);
	num="hello word";
}
void main()
{
	char *p=NULL;
	testCY(p);
	puts(p);
}

运行结果:报错;

分析:

test函数中的num指针和main函数中的p指针不是同一个指针,因为形参也可以看作成员变量;在test函数开辟的空间是给num指针开辟的,而不是给p指针开辟的,这时候的p指针一直为NULL;所以这时候报错;

3.可以取得值2

例子
void testCY(char **num)
{
	char *tmp = malloc(100);
	memset(tmp,0,100);
	strcpy(tmp,"hello word");
	*num = tmp;
}
void main()
{
	char *p=NULL;
	testCY(&p);
	puts(p);
	free(p);
}

运行结果:hello word

分析

首先将二级指针num的值赋值为一级指针p的地址值,再创建临时指针tmp,在堆中开辟一块空间,tmp指针指向这块内存,将“hello world”从常量区拷贝到这块内存,再将一级指针p指向tmp指向的地址,这样在函数结束后,二级指针num、一级指针tmp会被销毁,但是一级指针p已经指向了开辟的堆内存;

优化:不需要tmp也可以做到,用num代替tmp;

评论

博客
分类
标签
归档
关于