一、简单介绍
一般来说我们如果要在函数中去创建一个结构体的话,返回值一般都是返回一个指针,因为如果我们返回的是一个结构体的话,会消耗内存,因为在函数里面的内部创建的结构体,然后外面声明一个变量赋值给它,其实是做了一个拷贝操作,这样的话如果结构体有很多属性,就会消耗很多的内存,所以我们一般是把指向结构体的指针传递出去。下面都是在栈区开辟的空间,所创建的变量。所以是会存在问题的,因为是在子函数栈里面创建的,是有可能被销毁,所处栈空间的位置是有可能被覆盖的,下面主要是举例子说明下问题。
先看下结构体的结构
typedef struct {
int capacity;
int length;
int * value;
}LinearList;
然后如果向下面这样去写函数的话,也就是说返回值是一个结构体的话
LinearList listCreat(int capacity)
{
LinearList list;
list.capacity=capacity;
list.length=0;
list.value=NULL;
printf("%p\n",&list);
return list;
}
外界调用
LinearList list = listCreat(10);
printf("%p\n",&list);
打印出来的地址是不一样的
如果分别打印函数内的结构体内部的属性和外部的结构体的地址也是不一样的
所以其实这种方式就相当于是
而如果我们函数的返回值是指针类型,也就是说把函数写成这样
LinearList * listCreat(int capacity)
{
LinearList list;
list.capacity=capacity;
list.length=0;
list.value=NULL;
LinearList *pList = &list;
return pList;
}
那么外面的赋值其实就相当于是我一个指针指向这个结构体,也就是这样像下面这样赋值
LinearList * list = listCreat(10);
printf("%p",list);
这样我们去打印地址就都是相同的
相当于这样
使用LinearList * listCreat(int capacity)函数还有个问题就是我们创建的结构体,打印出来的地址都是一样的,因为所处的函数栈相同,这个函数栈里面的空间还没有被重新去设定,也就是说如果我们这样去创建结构体打印出来的地址值是一样的,还有就是刚开始我们去访问list2的capacity属性还可以正确访问到,但是当我们设置了几条打印语句,以及调用了另外一个函数之后,就开始出现问题了,所以就说明了其实栈区变量是不可靠的
int add(int a,int b)
{
printf("%p\n",&a);
return a+b;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
LinearList * list = listCreat(10);
LinearList * list1 = listCreat(20);
LinearList * list2 = listCreat(30);
printf("前%d\n",list2->capacity);
printf("%p\n",list);
printf("%p\n",list1);
printf("%p\n",list2);
printf("中%d\n",list2->capacity);
add(10,20);
printf("后%d\n",list2->capacity);
}
return 0;
}
打印结果如下所示
这里再补充下,我们可能在Xcode去打印 sizeof(int *) 和sizeof(void *) 打印出来的是8,这就代表占据8个字节,因为我们的系统是64位的,CPU是64位的,寄存器是64位的,也就是8个字节。