欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C是怎样使用内存的 博客分类: C\C++  

程序员文章站 2024-03-11 12:47:07
...

1、应用程序面对的地址实际是虚拟地址空间,每一个进程分配了一个独立的虚拟地址。

printf输出地址值输出的并不是真实的物理地址。

#include <stdio.h>

int main()
{
	int		hoge;
	char	buf[256];

	printf("&hoge...%p\n",&hoge);

	printf("input initial value.");
	/*由于scanf连续从流中读入字符(换行也是一个字符),而不是以单位内容进行解释。
	当输入"123\n"时候,scanf读取"123",而后面的getchar读取"\n"
	而fgets和sscanf组合使用可以避免这个问题
	*/
	fgets(buf,sizeof(buf),stdin);
	sscanf(buf,"%d",&hoge);

	for(;;)
	{
		printf("hoge...%d",hoge);
		getchar();  //等待回车
		hoge++;
	}
	return 0;
}

 让程序在两个窗口运行,发现打印的hoge地址相同,但是,他们数据并没有发生任何影响。

 

2、

C语言的变量有区间性的作用域。这种作用域有三种:全局变量(在函数之外声明的变量,在任何地方可见,用extern连接)、文件内部的静态变量(在函数之外声明的static变量,只在本文件中有效)、局部变量(函数内声明的变量)。

C语言的变量还有存储期的差别。静态存储期(全局变量、文件内部的静态变量、局部static变量的寿命从程序开始运行到结束都一直存在)、自动存储期(非static局部变量,用“栈“的机制来实现)。还有动态分配内存malloc,直到free为止。

  

现在输出各类指针的地址:

#include <stdio.h>
#include <stdlib.h>

int			global_var;
static int		file_static_var;

void fun1()
{
	int	f1_var;
	static int f1_static_var;
	printf("&f1_var...%p\n",&f1_var);
	printf("&f1_static_var...%p\n",&f1_static_var);
} 

void fun2()
{
	int	f2_var;
	static int f2_static_var;
	printf("&f2_var...%p\n",&f2_var);
	printf("&f2_static_var...%p\n",&f2_static_var);
}

int main()
{
	printf("fun1...%p\n",fun1);  //指向函数的指针
	printf("fun2...%p\n",fun2);
	printf("string...%p\n","abc");  //指向字符串常量的指针
	printf("&global_var...%p\n",&global_var);  //指向字符串常量的指针
	printf("&file_static_var...%p\n",&file_static_var);  //指向字符串常量的指针

	fun1();
	fun2();

	int *p=(int *)malloc(sizeof(int));
	printf("&p...%p\n",p);  //指向字符串常量的指针
	free(p);

	return 0;
}

 测试可以知道:

静态变量(全局变量、文件内static变量、函数内static变量)的地址很近。

函数指针、字符串常量的地址相对较近。

而自动变量f1_var和f2_var的地址一样,且离其他变量很远。

 

函数指针一般用于:1、GUI作为监听时候调用;2、用函数指针数组对行为进行分类处理。

 

函数自身的指针和字符串分配到“只读内存区域”。由于函数本身不可能修改、字符串常量不允许修改,所以它们放在只读内存区域。

 

静态变量从程序启动一直在内存中,也就是它们占有固定的区域。

 

自动变量存储在栈中,一旦函数结束运行,相应的自动变量的内存区域就会释放。

函数调用的过程如下:

  • 1、调用函数时,参数从后往前按顺序压栈。
  • 2、与函数相关的返回信息返回地址压栈。
  • 3、跳到被调用函数的地址。
  • 4、函数的自动变量压栈。
  • 5、计算,可能有时候会有值放到栈中。
  • 6、函数结束后,自动变量内存释放,使用返回信息返回原来的地址。
  • 7、栈中移除调用方的参数。

 malloc分配指定尺寸大小的内存块,返回内存块的首地址,如果分配失败(内存不足),返回NULL。这块内存需要用free来释放。像这种可以用任意顺序来释放的内存区域称为“堆”。

free需要注意的问题:调用free之后是不能引用对应的内存区域;但是,这块区域并不会马上被破坏掉。例如下面中pa释放掉了 ,但是pb还在用他。

int *pa;
pa=(int *)malloc(sizeof(int));
*pa=1234;
int *pb=pa;
free(pa);
pa=NULL;
printf("%d",*pb);

 在大型程序中,可以做一个函数给free披一张皮,并且程序猿只能调用这个函数,在释放区域之前故意将区域破坏(可以胡乱的用一个像0xcc这样的值填充)。

 

3、大小端

小端模式:数据低位位于低字节中,数据高位位于高字节中;数据地址是低字节地址。

 

int a=0x12345678;
unsigned char *pa=(unsigned char *)&a;

printf("%x  %p\n",pa[0],&pa[0]); //16进制整数输出第一个字节的值
printf("%x  %p\n",pa[1],&pa[1]); //16进制整数输出第一个字节的值
printf("%x  %p\n",pa[2],&pa[2]); //16进制整数输出第一个字节的值
printf("%x  %p\n",pa[3],&pa[3]); //16进制整数输出第一个字节的值

 测试结果为:

     78  0012FF60

     56  0012FF61

     34  0012FF62

     12  0012FF63

小端模式的数据存储如下:

                C是怎样使用内存的
            
    
    博客分类: C\C++  

 

4、字节对齐
 

  • C是怎样使用内存的
            
    
    博客分类: C\C++  
  • 大小: 6.4 KB