C/C++内存存储
#include <stdio.h>
#include "string.h"
#include "malloc.h"
void Swap(int a,int b)
{
int temp;
temp=a;
a=b;
b=temp;
}
int Get_Int(int a)
{
+a;
return i;
}
char* Get_Memory0()
{
);
strcpy(p,"hello world");
return p;
}
char* Get_Memory1()
{
char* p="hello world";
return p;
}
char* Get_Memory2()
{
char p[]="hello world";
return p;
}
void main()
{
,y=;
Swap(x,y);
int z=x-y;
printf("z=%d\n",z);
z=Get_Int(z);
printf("z=%d\n",z);
char* c0=Get_Memory0();
printf("c0=%s\n",c0);
const char* c1=Get_Memory1();
printf("c1=%s\n",c1);
char* const c2=Get_Memory2();
printf("c2=%s\n",c2);
}
复制代码
基础知识
内存存储:
在C/C++中,通常可以把内存理解成4个分区:栈、堆、全局/静态存储区和常量存储区。
()栈:通常是用那些在编译期间就能确定其存储大小的变量的存储区,用于在函数作用域内创建、在离开作用域后自动销毁的变量的存储区。通常是局部变量、函数参数等的存储区。它的存储空间是连续的,两个紧挨着的定义的局部变量,它们的存储空间是紧挨着的。栈的大小是有限的,通常Visual C++编译器默认栈的大小是1M,所以不要定义int a[]这样的超大数组。
()堆:通常是用于那些在编译期间不能确定存储大小的变量存储区,它的存储空间是不连续的,一般同malloc(或new)函数来分配内存块,并且需要要free(或delete)释放内存。如果程序员没有释放掉,那么就会出现常说的内存泄漏问题。需要注意的是,两个紧挨定义的指针变量,所指向的malloc出来的内存并不一定是紧挨着的。另外需要注意的一点是,堆的大小几乎是不受限制的,理论上每个程序最大可达4GB。
()全局/静态存储区:和“栈”一样,通常是用于那些在编译期间就能确定存储大小的变量的存储区,但它用于的是在整个程序运行期间都可见的全局变量和静态变量。
()常量存储区:和“全局/静态存储区”一样,通常是用于那些在编译期间就能确定存储大小的常量存储区,并且在程序运行期间,存储区内的常量也是全局可见的。这是一块比较特殊的存储区,它们里面放的是常量,不允许被修改。
程序解答:
()Swap函数:我们知道,所有函数都会在运行时从程序“栈”上得到分配给它的一块存储区(这里的“栈”就是前两面讲解内存存储时提到的“栈”,第个运行程序都拥有自己的运行时“栈”)。这块“栈”上的函数存储区随函数的开始面开始,随着函数的结束而结束。函数结束后,这块存储区就会自动释放,以供程序的其他用途使用。系统在函数运行时会为函数的每一个参数都提供存储区,参数在存储区中的存储长度由自身的类型决定。参数传递,就是系统用函数实参初始化函数参数存储区的过程。
函数的参数有传值(传指针)和传址(传引用)两种。所谓参会传值,就是实参的值复制到函数运行时分配给函数的参数存储区中。参数在传值时,函数不会访问当前调用的实参,函数处理的是实参在本地的拷贝,这些拷贝被存储在函数的“栈”中,所以这些拷贝值的改变不会影响实参的值。
答案:
z=
()问题:返回值i是一个局部变量,函数的返回参数怎么能是局部变量呢?局部变量在离开作用域后就自动被销毁了,还怎么能返回值给调用都呢?
解答:函数的返回值有传值和传址两种。int Get_Int(int a)属于返回值是传值的函数,这就意味着函数int Get_Int(int a)会在函数返回处产生一个临时对象,用于存放局部变量i的值的一份拷贝(变量i的右值的拷贝),临时对象是没有名称的,这份没有名称的对象的值(右值)会存储在调用者的“栈”中。所以当i作为局部变量离开作用域后,虽然被销毁了,但它的拷贝仍然存在,并在函数返回时作为“右值”赋给“左值z”。
答案:
z=
()此处考查对“堆”的理解:函数返回的是指向“堆”内存的指针。程序中malloc()是用于分配“堆”内存的库函数,而对于“堆”内存,只要程序中没有调用free()库函数去释放掉该“堆”内存,那么在程序运行期间,malloc()库函数分配的“堆”内存将一直存在。
)表示分配一块“堆”内存并使得变量p指向这块“堆”内存。
strcpy(p,"hello world")表示往p指向的“堆”内存中复制字符串hello world。
return p,变量p的左值是一个局部变量指针,存储于函数栈上,右值 是“堆”的地址(“堆”的值是hello world)。
函数char* Get_Memory0()属于返回值是传指针的函数,这就意味着函数char* Get_Memory0()会在函数返回处产生一个对返回变量p的“左值”的拷贝,也就是在“左值”的拷贝中存储了指向“堆”的地址。作为局部变量的 p,在离开函数作用域的时候虽然被销毁了,但函数返回值珠“左值”的拷贝是存在的,该拷贝存储了指向“堆“的地址,而而该“堆”的值是hello world。
答案:
c1=hello world
()这里考查对函数返回值和指针的理解:变量分为左值和右值,在char* p="hello world"中,左值是局部变量指针p,存储于函数栈上,右值是字符串常量hello world,存储于常量存储区。
char* Get_Memory1()属于返回值是传指针的函数,这就意味着函数char* Get_Memory1()会在函数返回处产生一个对返回对象的“左值”的拷贝,也就是在“左值”拷贝中存储了指向字符串常量hello world的地址。作为局部变量的p,在离开函数作用域的时候虽然被销毁了,但函数 返回的“左值”拷贝仍然存储了指向常量存储区的字符串常量hello world的地址。
答案:
c1=hello world
()和问题()有些相似,考查的也是对函数返回值和指针的理解:返回值是传指针,会在函数返回时产生“左值”拷贝。可以看到,p[]不是指针,是一个数组变量。编译器根据右值“hello world”的长度(12个字符)在编译期间在函数的栈上为数组分配大小为12个字符的内存存储区,其值是“hello world”。
通常,变量的意义在于,它给一块内存存储区提供名字,方便程序对这块内存进行读写。变量包含两个值:左值和右值。左值是内存存储区的名字,右值是存放存储区中的值。从程序中可以看到,函数返回的“左值”拷贝 指向的是局部变量数组p[]的首地址。当局部数组p[]作用域后会被自动销毁。这时,函数返回的“左值”拷贝指向的是一个被销毁的局部变量地址。
答案:
warning C4172: returning address of local variable or temporary
c2=未知
C/C++内存存储的更多相关文章
- Redis内存存储结构分析
1 Redis 内存存储结构 本文是基于 Redis-v2.2.4 版本进行分析. 1.1 Redis 内存存储总体结构 Redis 是支持多key-value数据库(表)的,并用 RedisDb 来 ...
- memcached全面剖析–2. 理解memcached的内存存储
Slab Allocation机制:整理内存以便重复使用 最近的memcached默认情况下采用了名为Slab Allocator的机制分配.管理内存. 在该机制出现以前,内存的分配是通过对所有记录简 ...
- C/C++内存存储问题
#include <stdio.h> #include "string.h" #include "malloc.h" void Swap(int a ...
- 1.C#基础学习笔记3---C#字符串(转义符和内存存储无关)
技术qq交流群:JavaDream:251572072 教程下载,在线交流:创梦IT社区:www.credream.com ------------------------------------- ...
- 【解惑】剖析float型的内存存储和精度丢失问题
问题提出:12.0f-11.9f=0.10000038,"减不尽"为什么? 现在我们就详细剖析一下浮点型运算为什么会造成精度丢失? 1.小数的二进制表示问题 首先我们要搞清楚下面两 ...
- Go Web:数据存储(1)——内存存储
数据可以存储在内存中.文件中.按二进制序列化存储的文件中.数据库中等. 1.内存存储 2.CSV文件存储 3.gob序列化存储 内存存储 将数据存储到内存中.此处所指的内存是指应用程序自身的内存空间( ...
- memcached全面剖析--2.理解memcached的内存存储
下面是<memcached全面剖析>的第二部分. 发表日:2008/7/9 作者:前坂徹(Toru Maesaka) 原文链接:http://gihyo.jp/dev/feature/01 ...
- spark 源码分析之十六 -- Spark内存存储剖析
上篇spark 源码分析之十五 -- Spark内存管理剖析 讲解了Spark的内存管理机制,主要是MemoryManager的内容.跟Spark的内存管理机制最密切相关的就是内存存储,本篇文章主要介 ...
- 32 位bitmap 内存存储 顺序 bgra 前3位 与23位一致。 都是 bgr 呵呵 与rgb 相反
32 位bitmap 内存存储 顺序 bgra 前3位 与23位一致. 都是 bgr 呵呵 与rgb 相反
随机推荐
- css的display属性小实验
div与span是常用的盒子模型; 区别: div默认是垂直分布(独占一行) span默认是水平分布(一行可以有多个) 通过float属性可以改变div容器的分布方式达到span容器的效果; 下面 ...
- LR(0)语法分析
# include <stdio.h> # include <string.h> //存储LR(0)分析表 struct node { char ch; int num; }; ...
- VS2013中设置大小写的快捷键
1.我们在定义头文件时,通常需要定义: #ifndef _MainMenu_H_#define _MainMenu_H_ your code... #endif 我们需要将头文件名设置为大写的: ...
- 二分查找or折半查找
package com.gxf.search; /** * 测试折半查找or二分查找 * @author xiangfei * */ public class BiSearch { /** * 非递归 ...
- js 正则 数值验证
function checkTextDataForNORMAL(strValue) { // 特殊字符验证格式 var regTextChar = /([\*"\'<>\/])+ ...
- HTTP 错误 500.21 - Internal Server ErrorHTTP
应用程序“DEFAULT WEB SITE/WINDRP_TB/TBFXWS”中的服务器错误Internet Information Services 7.5错误摘要HTTP 错误 500.21 - ...
- android 弹出框(输入框和选择框)
1.输入框: final EditText inputServer = new EditText(this); inputServer.setFilters(new InputFilter[]{new ...
- Ubuntu 查看文件以及磁盘空间大小命令df
(1)查看文件大小 查看当前文件夹下所有文件大小(包括子文件夹) du -sh # du -h 15M ./package 16K ./.fontconfig 4.0K ...
- 在ubuntu16.04 下安装haproxy 1.5.11 做tcp负载均衡
由于haproxy需要FQ下载,所以从csdn下载了较为新版的haproxy1.5.11,安装过程如下: 1. 解压haproxy-1.5.11.tar.gz : tar xzvf haproxy-1 ...
- Unity物理优化的一个小问题
为了性能优化,Unity会计算场景中所有的体积,包括静态的碰撞器并把 这些信息存在“Cash”中,对于静止物体而言,有了这些信息,就不需要 再每帧重新进行计算了.若移动,拉伸后或旋转了静态物体时,就是 ...