`

C是怎样使用内存的

 
阅读更多

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

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

                

 

4、字节对齐
 

  • 大小: 6.4 KB
分享到:
评论

相关推荐

    C语言内存使用详解 内存管理 内存调试 内存使用规则等

    《C语言内存使用详解——内存管理与调试》 在C语言编程中,理解内存的使用是至关重要的。本文将深入探讨内存的管理、调试以及使用规则,特别关注堆和栈的区别。 1. 堆与栈的区别 1.1 栈区 栈是程序运行时由编译器...

    C语言实现内存管理

    本主题将深入探讨如何使用C语言来实现内存管理的关键操作:创建、修改和删除。 1. **动态内存分配**: C语言提供了三种主要的动态内存分配函数:`malloc()`, `calloc()`, 和 `realloc()`。`malloc()`用于按需分配...

    C语言内存管理与内存泄露

    C语言内存管理是编程中的重要概念,特别是在C和C++这样的低级语言中,程序员需要直接处理内存分配和释放。内存管理分为静态内存、栈内存和堆内存三类。 1. 静态内存(Static Memory):这部分内存由编译器自动管理...

    C语言内存精讲,让你彻底明白C语言的运行机制!

    4. C语言内存对齐,提高寻址效率 5. 内存分页机制,完成虚拟地址的映射 6. 分页机制究竟是如何实现的? 7. MMU部件以及对内存权限的控制 8. Linux下C语言程序的内存布局(内存模型) 9. Windows下C语言程序的内存...

    C语言系列——C 内存管理详解

    在C语言中,内存管理是程序开发中至关重要的一部分,它涉及到程序如何有效地使用和释放内存。内存分为不同的区域,如静态存储区、栈和堆,它们各有特点和用途。 1. **内存分配方式** - **静态存储区域分配**:这...

    linux c程序获取cpu使用率及内存使用情况

    linux c程序获取cpu使用率及内存使用情况

    C 共享内存读写 2个程序之间传输数据

    下面将详细阐述C语言中使用共享内存进行读写操作以及在两个程序间传输数据的原理和步骤。 首先,让我们理解共享内存的基本概念。共享内存是一种特殊的内存映射文件,它可以被多个进程同时访问。在Linux中,我们可以...

    C 语言检测内存泄露的方法(例子)

    总的来说,检测C语言中的内存泄漏需要结合多种方法,包括编写自定义的内存管理函数、使用专门的内存检测工具以及进行代码审查。通过深入理解这些示例代码,我们可以更好地掌握内存管理技巧,防止因内存泄漏导致的...

    C语言读取文件数据,写入内存

    在C语言中,读取文件数据并将其写入内存是一项基本操作,对于任何涉及文件处理的项目都至关重要。本文将详细介绍如何使用C语言实现这一功能,同时也会提及一些相关的编程概念和技术。 首先,理解文件在计算机中的...

    操作系统 内存分配与回收 C语言模拟(含源代码和.exe文件)

    在本项目中,`main.c`文件很可能是实现这些策略的C语言代码。 4. **内存回收**:内存回收是动态内存管理的重要部分,确保已分配的内存块在不再使用时被正确释放。未正确回收的内存可能导致内存泄漏,随着时间的推移...

    C语言内存精讲.rar

    理解指针的工作原理,包括指针的声明、使用和指针运算,是掌握C语言内存管理的关键。 6. **内存泄漏检测**:为了找出程序中的内存泄漏,可以使用特定的工具如Valgrind,或者编写特定的代码片段来检查内存分配和释放...

    C语言实现完整功能的内存池

    实现内存池的关键在于高效的数据结构和算法,以及对C语言内存管理的深入理解。例如,可以使用双向链表来链接所有空闲块,便于插入和查找;通过位图表示内存块的状态,快速定位空闲块;使用内存池可以减少系统调用...

    C语言中的内存管理

    内存管理是编程中至关重要的一个环节,特别是在C语言中,程序员需要手动进行内存的分配与释放。理解C语言中的内存管理有助于我们编写出更高效、更健壮的程序。 首先,内存分配有三种主要方式: 1. 静态存储区域...

    C语言中级-6内存使用

    在C语言中,内存管理是编程过程中的一个关键部分,特别是在中级阶段,理解并熟练掌握内存使用至关重要。本文将深入探讨C语言中的内存区域、内存分配方式以及如何有效地使用内存。 1. 内存区域 C语言中的内存分为三...

    C语言内存管理

    C语言内存管理是一个程序员必须掌握的重要知识点,因为它直接关系到程序运行的稳定性和效率。内存泄漏是C语言中一个非常典型的问题,指的是程序中分配的堆内存无法再被访问或回收,最终导致可用内存不断减少。内存...

    C语言学习资料 C 数组 内存使用 结构体等

    在编程世界中,C语言是一种基础且强大的编程语言,它为程序员提供了低级内存操作的能力,使得编写高效、性能优异的程序成为可能。本学习资料主要涵盖了C语言中的数组、内存管理和结构体等核心概念,适合C语言的初学...

    内存池(C语言实现)

    开发者可以使用这些API在自己的C语言项目中实现内存池管理。 使用内存池有以下优势: - **减少碎片**:内存池中的内存分配和释放都是在池内进行,避免了系统级的内存碎片。 - **提高性能**:通过减少系统调用,内存...

    C语言中级教程-6 内存使用

    C语言中级教程-6 内存使用

    c语言内存管理.pdf

    ### C语言内存管理知识点 #### 一、C语言内存管理概览 在C语言中,内存管理是一项核心技能,尤其对于高效程序设计至关重要。本文档将深入探讨C语言中的内存管理机制,帮助开发者理解不同类型的内存分配以及如何...

Global site tag (gtag.js) - Google Analytics