SmartPtr
本博客已搬至:http://www.cnblogs.com/baiyanhuang/
posts - 29,comments - 176,trackbacks - 0
By SmartPtr(http://www.cppblog.com/SmartPtr/) 
 
 今天收到学弟的一封信,问我关于变量与内存的一些问题,其实这是一个很基本的概念,但可能还有很多人对这个还不太了解(包括自己可能也会有误解的地方),遂将原信与回信放于此:
  
原信
问几个我比较混乱的问题。
看一下我写的对不对
int g_variable; //占编译后的代码空间,运行时占内存(常住内存)
const int c_value = 5;    //占编译后的代码空间, 是不是常住内存呢?
void fun(void)
{
static int s_variable;    //占编译后的代码空间,运行时占内存(常住内存)
int variable;    //fun 被调用时放入栈中(占用内存)
}
如果我定义一下大一点的数组,如:
const int c_array[100] = ...;
程序一运行时就会被分配 400 Byte 的内存空间吗?还是在我使用它时会被分配400 Byte 的内存空间吗?

回信
先给你大概讲一下基本概念, 问题在原信下用红色回答
 
一个程序的运行起来后,其在内存中有5个区域
1. 程序代码区
这个很简单,存放执行指令,代码要执行,肯定要加载进内存, 我们不必关心。
 
2. 文字常量区
一般我们这样定义一个字符串时,其是在文字常量区的:
char* s1 = "hello, world";
char* s2 = "hello, world";
if(s1 == s2)
  printf("s1和s2指向同一个在文字常量区的字符串");
 
这里, s1和s2指向的是同一个字符串
 
3. 静态存储区
全局变量,静态变量会放在这个区域,事实上,全局变量也是静态的。
 
以上1,2,3三个区域的内存在程序起来的时候就开辟好了的。
 
4. 栈
局部变量就是在栈里的。另外,函数调用时的参数也是在栈里的,这个现在不必关心
 
5. 堆
malloc或new出来的内存就是在堆里的,需要程序员自己管理清除。


**********原信***************************************************

问几个我比较混乱的问题。
看一下我写的对不对
 
int g_variable; //占编译后的代码空间,运行时占内存(常住内存)
[Huang]属于3,程序一运行就占内存,知道程序退出才释放
 
const int c_value = 5;    //占编译后的代码空间, 是不是常住内存呢?
[Huang]其实这个与是否const无关,如果这句是全局的,那么同上,如果是局部的,那么属于4
 
void fun(void)
{
static int s_variable;    //占编译后的代码空间,运行时占内存(常住内存)
int variable;    //fun 被调用时放入栈中(占用内存)
}
[Huang]第一句属于3, 第二句属于4
 
如果我定义一下大一点的数组,如:
 
const int c_array[100] = ...;
 
程序一运行时就会被分配 400 Byte 的内存空间吗?还是在我使用它时会被分配400 Byte 的内存空间吗?
[Huang]还是那句话,是全局的,那么 程序一运行时就会被分配 400 Byte 的内存空间, 如果是局部的,那么在我使用它时会才会被分配400 Byte 的内存空间
 
你这里多次提到const, 其实const与这个主题并没有关系。的确,const与static声明的全局变量具有内部链接的特性,但是即使在每个obj里都有一个此变量的拷贝,也不影响其内存在静态区的分配。
posted on 2007-09-13 00:01 SmartPtr 阅读(1105) 评论(5)  编辑 收藏 引用

FeedBack:
# re: 答学弟问之变量与内存问题
2007-09-13 00:36 | aGAric
还有一点,如果你的全局变量是初始化过的
比如
staitc int array[100] = {0};

那么你的编出来的.o ,或者是.exe也会大出 100*sizeof(int)。 如果没有初始化,那么他们放在bss段,就不占程序code的大小了。

const 还是有区别的, const的变量可能是在只读的数据区域。  回复  更多评论
  
# re: 答学弟问之变量与内存问题
2007-09-13 09:05 | SmartPtr
我的理解是这样的:
1. 静态存储区又分为静态初始化存储区和静态未初始化存储区,正如你说的,前者对应.data段,后者对应bss段, 但是不论在哪个段,都要占程序内存空间的吧

2. const变量应该只是编译器语法上的一个限制,数据会在哪个存储区并不由其决定, 事实上, 绕过C++语法,改变const值是很容易的:
const int ci = 10;
__asm
{
mov eax, 100;
mov ci, eax;
}  回复  更多评论
  
# re: 答学弟问之变量与内存问题
2007-09-13 23:27 | aGAric
bss段只记着这里有一个数组,大小是多少就占一点空间,data段里面需要占用整个变量的大小。

某些编译器的实现,确实会把const 的数据放在只读段, 你当然可以写那个地址,但系统可能会抛出一个异常。  回复  更多评论
  
# re: 答学弟问之变量与内存问题
2008-08-19 11:42 | Matrix
这样改不了const的值哇@SmartPtr
  回复  更多评论
  
# re: 答学弟问之变量与内存问题
2008-09-17 22:54 | Dandelion
添加volatile关键字,就看到了
const volatile int ci = 10;
__asm
{
mov eax, 100;
mov ci, eax;
}

不加volatile关键字的话,编译器发现在自己的可见范围内ci没有被改变,于是就假设_asm{}之后ci的值没变,导致生成的汇编代码为:
push 0Ah

加了关键字后,编译器就不会对ci做任何的假设,于是生成的汇编代码变成了这样:
mov eax,dword ptr[i]
push eax  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理