目录
一个主程序有n函数组成,c++编译器会建立有几个堆区?有几个栈区?
栈的生长属性是开口向上的还是开口向下的?
栈的特点是先进后出,利用这个特点可以测出栈的生长方向是开口向上还是向下 。那如何测呢?先定义一个总方向,Y轴,向上地址值越大,向下地址值越小。那么,我可以写两个变量a,b。先让a入栈,再让b入栈。a、b入栈都会给其分配内存空间,如果给b分配的地址比给a分配的地址大, 那么就说明开口向上,反之开口向下。
那么根据程序进行测试:
void main71()
{
int a;
int b ;
printf("&a:%d , &b: %d \n", &a, &b);
system("pause");
return ;
}
运行结果如下,a先进,b后进。发现给b分配的地址比给a分配的地址小。可以证明栈区的开口方向是向下的。
常识性的结论: 一般情况下,操作系统为用户搭建的内存四区的开口方向是向下的。应该说的是,不同的编译器,对应的开口方向是不确定的。对这个事情有个了解就行了,一般是向下的,但不可一概而论。
这样设计的缘故是为了避免栈的溢出。如果我们提前把栈的最大值给设定好,向下压栈的过程,栈的剩余空间会越来越小,防止栈的溢出。
那么,引入另一个问题,如果我在栈里引入一个变量buf:
char buf[128]; //静态编译的时候 buf所代表的内存空间的标号 就已经定义下来了....
不管栈的生长方向是向下还是向上,变量buf的内存地址buf+1,生长方向都是向上的。这是因为这个是静态编译,言外之意就是,在你编译之前就确定好你设置的内存的起点和终点是那,有没有超过范围。而如果是在开口向下的栈中,buf的内存首地址,就是在靠下部分开始往上生长;如果是在开口向上的栈中,buf的内存首地址,依旧就是在靠下部分开始往上生长。
函数调用模型
假设一个运行程序,一个主程序main,其中,第十行有子函数fa,子函数fa中又嵌套一个子函数fb,那这三个函数之间的调用模型是怎么样的呢?
main函数正常运行,把需要的入栈的变量入栈,需要出栈的变量运行进行出栈,当到第十行发现有个内嵌的子函数fa的时候,提前把第十一行代码入栈,然后,开始执行fa,把子函数fa需要入栈的变量入栈,再在fa中遇到fb,同样,再把fb对应的函数内容入栈,当fb,执行完后,把fb在栈中的内容都出栈出完了,栈中才会执行fa之前留在栈中的内容。同理,当fa中的在栈中的部分执行完了,主函数才会开始执行自己的。之所以说,提前把第十一行代码入栈,是因为栈的先进后出结构,第十一行代码内容先压入栈,再压入fa,意思就是,fa的部分不执行完,就不去回到main中的执行流程中来。只要开始执行第十一行代码,就代表fa中的内容已经执行完毕了。
内存的使用范围
1.main函数中的变量可以在栈区,堆区,全局区分配内存,并且因为main函数在程序执行的环节当中,不会执行完(main执行完,就代表着程序运行完了,就不在程序执行环节当中了,换句话理解,只要main没执行完,程序就一直在运行着),所以,main里面分配的内存空间不会消失,可以供main里面的子函数(fa、fb)进行使用。
2.如果是在子函数(如,fa,fb)中生成内存,可以被main使用吗?答:如果是fb中在栈上分配的内存,那就不能被fa和main函数使用;如果fb是在malloc中分配的内存(堆),可以被main和fa函数使用的;如果fb是在全局区中分配的内存,可以被main和fa函数使用的;
一个主程序有n函数组成,c++编译器会建立有几个堆区?有几个栈区?
答:C++编译器会为每一个应用程序只建立一个内存四区,一个应用程序内的函数共同使用相同的内存四区,一个应用程序只有一个主程序函数(main函数)。内存四区相当于程序的执行空间。
完整代码
dm07_堆栈的属性测试.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//栈的开口向上向下,,测试 release和dubug;
//一般认为:栈开口向下
//不管栈开口向上还是向下,buf的内存地址buf+1,永远向上的..
void main71()
{
int a;
int b ;
char buf[128]; //静态联邦的时候 buf所代表的内存空间的标号 就已经定义下来了....
printf("&a:%d , &b: %d \n", &a, &b);
system("pause");
return ;
}