首页 > 代码库 > 面试经常问的C语言变量在内存中的分布(VC6.0)

面试经常问的C语言变量在内存中的分布(VC6.0)

C/C++变量在内存中的分布在笔试时经常考到,虽然简单,但也容易忘记,因此在这作个总结,以加深印象。

一:

#include <stdio.h>
#include <malloc.h>
int g_i = 100;
int g_j = 200;
int g_k, g_h;
int main()
{
	const int MAXN = 100;
	int *p = (int*)malloc(MAXN * sizeof(int));
	static int s_i = 5;
	static int s_j = 10;
	static int s_k;
	static int s_h;
	int *pi = new int(1);
	int *pj = new int(1);
	int i = 5;
	int j = 10;
	int k = 20;
	int f, h;
	char *pstr1 = "MoreWindows123456789";
	char *pstr2 = "MoreWindows123456789";
	char *pstr3 = "Hello";
	
	
	printf("堆中数据地址:0x%08x\n", p);
	printf("堆中数据地址:0x%08x\n", pi);
	printf("堆中数据地址:0x%08x\n", pj);

	putchar('\n');
	printf("栈中数据地址(有初值):0x%08x = %d\n", &i, i);
	printf("栈中数据地址(有初值):0x%08x = %d\n", &j, j);
	printf("栈中数据地址(有初值):0x%08x = %d\n", &k, k);
	printf("栈中数据地址(无初值):0x%08x = %d\n", &f, f);
	printf("栈中数据地址(无初值):0x%08x = %d\n", &h, h);
	
	putchar('\n');
	printf("静态数据地址(有初值):0x%08x = %d\n", &s_i, s_i);
	printf("静态数据地址(有初值):0x%08x = %d\n", &s_j, s_j);
	printf("静态数据地址(无初值):0x%08x = %d\n", &s_k, s_k);
	printf("静态数据地址(无初值):0x%08x = %d\n", &s_h, s_h);
	
	putchar('\n');
	printf("全局数据地址(有初值):0x%08x = %d\n", &g_i, g_i);
	printf("全局数据地址(有初值):0x%08x = %d\n", &g_j, g_j);
	printf("全局数据地址(无初值):0x%08x = %d\n", &g_k, g_k);
	printf("全局数据地址(无初值):0x%08x = %d\n", &g_h, g_h);
	
	putchar('\n');
	printf("字符串常量数据地址:0x%08x 指向 0x%08x 内容为-%s\n", &pstr1, pstr1, pstr1);
	printf("字符串常量数据地址:0x%08x 指向 0x%08x 内容为-%s\n", &pstr2, pstr2, pstr2);
	printf("字符串常量数据地址:0x%08x 指向 0x%08x 内容为-%s\n", &pstr3, pstr3, pstr3);
	free(p);
	return 0;
}

运行结果(不同的机器运行的结果(相对位置)会略有不同,因为堆栈、全局变量等分布是由操作系统决定的)


总之,字符串常量和栈中数据相邻(栈中无论有无初值总是在一起);有初值全局和静态变量一起,无处置的全局和静态变量一起,并且相邻;堆自己再占一块,并且不是连续的,是链表的形式。除了栈中的变量(局部变量和参数),先声明的地址在高位,后声明在低位。

二:

#include <stdio.h>
void fun(int i)
{
	int j = i;
	static int s_i = 100;
	static int s_j;
	
	printf("子函数的参数:        0x%p = %d\n", &i, i);
	printf("子函数 栈中数据地址: 0x%p = %d\n", &j, j);
	printf("子函数 静态数据地址(有初值): 0x%p = %d\n", &s_i, s_i);
	printf("子函数 静态数据地址(无初值): 0x%p = %d\n", &s_j, s_j);
}
int main()
{
	int i = 5;
	static int s_i = 100;
	static int s_j;
	
	printf("主函数 栈中数据地址: 0x%p = %d\n", &i, i);
	printf("主函数 静态数据地址(有初值): 0x%p = %d\n", &s_i, s_i);
	printf("子函数 静态数据地址(无初值): 0x%p = %d\n", &s_j, s_j);
	putchar('\n');
	
	fun(i);
	return 0;
}


总之,主函数中栈的地址都要高于子函数中参数及栈地址,证明了栈的伸展方向是由高地址向低地址扩展的。主函数和子函数中静态数据的地址也是相邻的,说明程序会将已初始化的全局变量和表态变量分配在一起,未初始化的全局变量和表态变量分配在另一起。

三 知识补充:

 c++内存到底分几个区?
 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
 2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由os回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
 3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放。
 4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放。
 5、程序代码区—存放函数体的二进制代码


1 变量可以存储在内存的不同地方,这依赖于它们的生成期。在函数上部定义的变量(全局变量或static外部变量)和在函数内部定义的static变量,其生存期就是程序运行的全过程。这些变量被存储在数据段(Data Segment)中。数据段是在内存中为这些变量留出的一段大小固定的空间,它分为二部分,一部分用来初始化变量,另一部分用来存放未初始化的变量。
2 在函数内部定义的auto变量(没有用关键字static定义的变量)的生成期从程序开始执行其所在的程序块代码时开始,到程序离开该程序块时为止。作为函数参数的变量只在调用该函数期间存在。这些变量被存储在栈(stack)中。栈是内存中的一段空间,开始很小,以后逐渐自动变大,直到达到某个预定义的界限。
3 当用malloc等函数给指针分配一个地址空间的时候,这个分配的内存块位于一段名为“堆(heap)”的内存空间中。堆开始时很小,但调用malloc或clloc等内存分配函数时它就会增大。堆可以和数据段或栈共用一个内存段,也可以有它自己的内存段,这完全取决于编译选项和操作系统。与栈相似,堆也有一个增长界限,并且决定这个界限的规则与栈相同。


面试经常问的C语言变量在内存中的分布(VC6.0)