网站演示程序,上虞区住房和城乡建设部网站,红酒商城网站建设,成都哪家做网站建设比较好在谈述函数调用和返回值问题之前#xff0c;先来看看C中内存分配的问题。 C编译器将计算机内存分为代码区和数据区#xff0c;很显然#xff0c;代码区就是存放程序代码#xff0c;而数据区则是存放程序编译和执行过程出现的变量和常量。数据区又分为静态数据区、动态数据区… 在谈述函数调用和返回值问题之前先来看看C中内存分配的问题。 C编译器将计算机内存分为代码区和数据区很显然代码区就是存放程序代码而数据区则是存放程序编译和执行过程出现的变量和常量。数据区又分为静态数据区、动态数据区动态数据区包括堆区和栈区。 以下是各个区的作用 (1)代码区存放程序代码 (2)数据区 a.静态数据区: 在编译器进行编译的时候就为该变量分配的内存存放在这个区的数据在程序全部执行结束后系统自动释放生命周期贯穿于整个程序执行过程。 b.动态数据区包括堆区和栈区 堆区这部分存储空间完全由程序员自己负责管理它的分配和释放都由程序员自己负责。这个区是唯一一个可以由程序员自己决定变量生存期的区间。可以用malloc,new申请对内存并通过free和delete释放空间。如果程序员自己在堆区申请了空间又忘记将这片内存释放掉就会造成内存泄露的问题导致后面一直无法访问这片存储区域。 栈区存放函数的形式参数和局部变量由编译器分配和自动释放函数执行完后局部变量和形参占用的空间会自动被释放。效率比较高但是分配的容量很有限。 注意:1)全局变量以及静态变量存放在静态数据区; 2)注意常量的存放区域通常情况下常量存放在程序区(程序区是只读的因此任何修改常量的行为都是非法的)而不是数据区。有的系统也将部分常量分配到静态数据区比如字符串常量(有的系统也将其分配在程序区)。但是要记住一点常量所在的内存空间都是受系统保护的不能修改。对常量空间的修改将造成访问内存出错一般系统都会提示。常量的生命周期一直到程序执行结束为止。 在弄懂内存分配的问题过后来看看函数调用的过程 执行某个函数时如果有参数则在栈上为形式参数分配空间如果是引用类型的参数则类外继续进入到函数体内部如果遇到变量则按情况为变量在不同的存储区域分配空间如果是static类型的变量则是在进行编译的过程中已经就分配了空间函数内的语句执行完后如果函数没有返回值则直接返回调用该函数的地方即执行远点如果存在返回值则先将返回值进行拷贝传回再返回执行远点函数全部执行完毕后进行退栈操作将刚才函数内部在栈上申请的内存空间释放掉。 下面通过几个例子来谈谈内存分配和函数返回值的问题 内存分配的问题 int a1; a在栈区 char s[]123; s在栈区“123”在栈区其值可以被修改 char *s123; s在栈区“123”在常量区其值不能被修改 int *pnew int; p在栈区申请的空间在堆区p指向的区域 int *p(int *)malloc(sizeof(int)); p在栈区p指向的空间在堆区 static int b0; b在静态区 1.test1 #includeiostreamusing namespace std;void test(int *p){ int b2; pb; coutpendl;}int main(void){ int a10; int *pa; coutpendl; test(p); coutpendl; return 0;} 第一行输出和第三行输出的结果相同而第一行、第三行与第二行输出的结果不同。从这里可以看出当指针作为参数进行传递时传递的也只是一个值只不过该值只一个地址因此对于形参的改变并不影响实参。 2.test2 #includeiostreamusing namespace std;char* test(void){ char str[]hello world!; return str;}int main(void){ char *p; ptest(); coutpendl; return 0;} 输出结果可能是hello world!,也可能是乱麻。 出现这种情况的原因在于在test函数内部声明的str数组以及它的值hello world”是在栈上保存的当用return将str的值返回时将str的值拷贝一份传回当test函数执行结束后会自动释放栈上的空间即存放hello world的单元可能被重新写入数据因此虽然main函数中的指针p是指向存放hello world的单元但是无法保证test函数执行完后该存储单元里面存放的还是hello world所以打印出的结果有时候是hello world有时候是乱麻。 3.test3 #includeiostreamusing namespace std;int test(void){ int a1; return a;}int main(void){ int b; btest(); coutbendl; return 0;} 输出结果为 1 有人会问为什么这里传回来的值可以正确打印出来不是栈会被刷新内容么是的确实在test函数执行完后存放a值的单元是可能会被重写但是在函数执行return时会创建一个int型的零时变量将a的值复制拷贝给该零时变量因此返回后能够得到正确的值即使存放a值的单元被重写数据但是不会受到影响。 4.test4 #includeiostreamusing namespace std;char* test(void){ char *phello world!; return p;}int main(void){ char *str; strtest(); coutstrendl; return 0;} 执行结果是 hello world! 同样返回的是指针为什么这里会正确地打印出hello world1这是因为char *phello world!指针p是存放在栈上的但是hello world!”是一个常量字符串因此存放在常量区而常量区的变量的生存期与整个程序执行的生命期是一样的因此在test函数执行完后str指向存放“hello world!”的单元并且该单元里的内容在程序没有执行完是不会被修改的因此可以正确输出结果。 5.test5 #includeiostreamusing namespace std;char* test(void){ char *p(char *)malloc(sizeof(char)*100); strcpy(p,hello world); return p;}int main(void){ char *str; strtest(); coutstrendl; return 0;} 运行结果 hello world 这种情况下同样可以输出正确的结果是因为是用malloc在堆上申请的空间这部分空间是由程序员自己管理的如果程序员没有手动释放堆区的空间那么存储单元里的内容是不会被重写的因此可以正确输出结果。 6.test6 #includeiostreamusing namespace std;void test(void){ char *p(char *)malloc(sizeof(char)*100); strcpy(p,hello world); free(p); if(pNULL) { coutNULLendl; }}int main(void){ test(); return 0;} 没有输出 在这里注意了free()释放的是指针指向的内存注意释放的是内存不是指针这点非常非常重 要指针是一个变量只有程序结束时才被销毁。释放了内存空间后原来指向这块空间的指针还是存在只不过现在指针指向的内容的垃圾是未定义的所以说是垃圾。因此释放内存后应把把指针指向NULL防止指针在后面不小心又被使用造成无法估计的后果。