前言
问题的来源于在学数据结构的时候,C++的语法和C语言的语法竟然不一样。
1.首先函数的参数有两种传递方式,一个是值传递,一个是地址传递。当指针作为参数传递的时候,即为地址传递,但C++写的时候需要加&引用符号,而C语言却不用。
2.本文谈的是这个问题,即为当声明一个结构体指针时,为什么还有new(C++)或者malloc()这种语句,一直搞不清楚,后台问bb,然后百度了一下,才明白
正文
看到一篇文章是这么写的
问题描述:
主题:定义结构体指针时,有没有同时分配存储空间
定义结构体指针时,有没有同时分配存储空间啊?
看到结构体的数组定义好以后就直接可以用了。
但是结构体指针在链表中还要malloc()申请空间。
这是为什么啊?
看到结构体的数组定义好以后就直接可以用了。
但是结构体指针在链表中还要malloc()申请空间。
这是为什么啊?
1楼:
定义结构体指针时并没有分配存储空间,所以要用malloc()申请空间。
2楼:
很明显,你还没有搞清楚什么是指针,至于结构体变量和结构体指针,更是很混淆,所以这里不是因为数组的问题。
举个例子:
举个例子:
//下面仅仅是定义一个类型,不会产生变量,所以不存在分配空间的问题
struct data
{int i;int j;
};void main(void)
{struct data dat1; //定义一个struct data类型的变量,和int i同理。printf("%d\n", sizeof(struct data)); //8个字节printf("%d\n", sizeof(dat1)); //8个字节struct data* pdat1;//定义一个struct data类型的指针,和int *pi 同理。printf("%d\n", sizeof(pdat1)); //4个字节,就是一个指针的空间,pdat1并没有结构体变量的信息。pdat1 = (struct data*)malloc(sizeof(struct data)); //申请一个空间,把该空间地址给pdat1.printf("%d\n", sizeof(*pdat1)); //8个字节struct data dats1[2]; printf("%d\n", sizeof(dats1)); //16个字节,两个data变量,不是data指针。dats1[0].i = 20; //可以直接使用数组里面的结构体变量dats1[0].j = 30;struct data* dats2[2]; //指针数组,包含两个指针,而不是结构体变量printf("%d\n", sizeof(dats2)); //8个字节,两个指针的大小dats2[0]->i = 20; //错误!还没有给dats2[0] 指针分配空间dats2[0]->i = 20; //错误!还没有给dats2[0] 指针分配空间dats2[0] = (struct data*)malloc(sizeof(struct data)); //分配空间dats2[0]->i = 20; //okdats2[0]->i = 20; //ok
}
3楼
声明任何对象并定义变量,包括指针都会开辟空间,除了静态成员在一个特别的区,其他的在栈上开辟空间,不用了自动清理,用malloc, realloc, calloc, new new[]开辟空间是动态分配空间,在堆上进行。值得说明的是,栈空间很小(相对于堆而言),很"昂贵",但是通常执行更快。
在Windows下,一个进程的栈在最高端,向下增长,堆在栈下面,向栈的方向增长,下面是数据和代码。Linux下内存布局由开发工具和操作系统合作负责,这四个部分相对位置布局不确定。
Windows下一个进程的线性地址空间布局:
--------------------
|
|
栈 V
V
V
--------------------
^
^
堆 |
|
|
--------------------
其他
在Windows下,一个进程的栈在最高端,向下增长,堆在栈下面,向栈的方向增长,下面是数据和代码。Linux下内存布局由开发工具和操作系统合作负责,这四个部分相对位置布局不确定。
Windows下一个进程的线性地址空间布局:
--------------------
|
|
栈 V
V
V
--------------------
^
^
堆 |
|
|
--------------------
其他
4楼
windows默认栈大小是1M
栈和堆是共享一内存的,可以调节它们的比例。来设置栈和堆的大小。
不过一般情况下,还是用不着的。。
栈和堆是共享一内存的,可以调节它们的比例。来设置栈和堆的大小。
不过一般情况下,还是用不着的。。
5楼
[quote]
有人告诉我:
A a[3]; a是A型的,有3个,当然分配A乘3大小的空间
A* a; a是A*型的,当然只分配A*大小的空间,而不会分配A大小的空间
好像跟你说的不太一样,结构体数组的话,我在课本里看到的确不用再次申请空间了啊[/quote]
结构体变量分配结构体本身大小的空间,结构体指针分配4个字节,其实任何类型的指针都是分配四个字节的指针空间。
所以:
A a[3]; //a里面是三个A变量,所以分配三个结构体大小
A *a; //a是一个指针,分配4个字节,就算A再大,a也只是4个字节,因为任何类型的指针都是4个字节。要使用a,必须先要对指针初始化,也即分配空间了。
如:
A *a;
a = (A*)malloc(sizeof(A));
我们完全可以撇开结构体,把问题简单化成int类型来说明这个指针问题:
int a1[10];
int *a2;
很容易知道,a1是包含10个int的数组,大小也就是10*sizeof(int)。我们可以直接使用a1不要在进行什么初始化或者分配空间的游戏,因为数组a1里面本身存放的就是int变量本身了。
然后a2,是一个int*的东西,也就是整型指针,a2不能存放int变量,它只能存放地址,一个int变量的地址。如果要使用a2,必须首先对a2初始化,即将它指向一个int变量的地址,如:
a2 = (int*)malloc(sizeof(int));
或者
int i = 10;
a2 = &i;
所以,malloc函数的作用是首先声明一个变量,然后返回该变量的地址。
所以:a2 = (int*)malloc(sizeof(int)) 的含义就是把该变量的地址赋值给a2,和a = &i 本质上并没有什么不同,只是一个变量是栈上,一个是堆上,都是一个地址赋值。
所以,所谓的分配空间,就是对指针赋值,把一个变量的地址赋值给一个指针。
有人告诉我:
A a[3]; a是A型的,有3个,当然分配A乘3大小的空间
A* a; a是A*型的,当然只分配A*大小的空间,而不会分配A大小的空间
好像跟你说的不太一样,结构体数组的话,我在课本里看到的确不用再次申请空间了啊[/quote]
结构体变量分配结构体本身大小的空间,结构体指针分配4个字节,其实任何类型的指针都是分配四个字节的指针空间。
所以:
A a[3]; //a里面是三个A变量,所以分配三个结构体大小
A *a; //a是一个指针,分配4个字节,就算A再大,a也只是4个字节,因为任何类型的指针都是4个字节。要使用a,必须先要对指针初始化,也即分配空间了。
如:
A *a;
a = (A*)malloc(sizeof(A));
我们完全可以撇开结构体,把问题简单化成int类型来说明这个指针问题:
int a1[10];
int *a2;
很容易知道,a1是包含10个int的数组,大小也就是10*sizeof(int)。我们可以直接使用a1不要在进行什么初始化或者分配空间的游戏,因为数组a1里面本身存放的就是int变量本身了。
然后a2,是一个int*的东西,也就是整型指针,a2不能存放int变量,它只能存放地址,一个int变量的地址。如果要使用a2,必须首先对a2初始化,即将它指向一个int变量的地址,如:
a2 = (int*)malloc(sizeof(int));
或者
int i = 10;
a2 = &i;
所以,malloc函数的作用是首先声明一个变量,然后返回该变量的地址。
所以:a2 = (int*)malloc(sizeof(int)) 的含义就是把该变量的地址赋值给a2,和a = &i 本质上并没有什么不同,只是一个变量是栈上,一个是堆上,都是一个地址赋值。
所以,所谓的分配空间,就是对指针赋值,把一个变量的地址赋值给一个指针。
----------我是萌萌哒分割线----------
很明显三楼和四楼讲的有点底层了,不过其他楼层说的很明白,首先只是分配了指针本身的存储空间,指针指针还没有被赋值,通过new或者malloc()语句是为了给结构体变量分配内存空间,即为指针赋值,即指针指向的内容的信息,便有了指针指向的数据内容和空间。
----------我是萌萌哒分割线----------
原文地址:http://bbs.pfan.cn/post-284115.html