C语言程序内存地址分布!!

变量

在讲C语言程序内存地址分布之前,先讲讲关于C语言的变量:
大体上分为三种:
	1.块变量
		在语句块(函数里面的分支或者循环语句中或者 {} )中定义,只能在定义的语句块中使用。
		作用域:语句块
		{
			//块变量
		}
	2.局部变量
		在函数内部定义的(除块变量以外),形参是局部变量,只能在函数内部访问。
		作用域:函数内部
	3.全局变量
		定义在函数外部的变量  在程序中都可以访问
		作用域:整个程序
	
	下方举例说明各中变量:
  1 #include<stdio.h>
  2 int p;//全局变量
  3 
  4 void a(){
  5     int i ;//局部变量
  6 }
  7 int main(){
  8     int i = 100;//局部变量
  9     for(i=0;i<100;i++){
 10         int j = i+1;//块变量
 11     }   
 12     return 0;
 13 }  
同时在定义变量时有一些注意点:
	1.在同一个作用域下面,不能定义和声明同名的变量,但是在块变量中可以定义和局部变量同名的变量,在函数中可以定义和全局同名的变量。
	2.局部优先原则:块变量-->局部变量-->全局变量
	3.如何访问呗隐藏掉的全局变量:
		1).写个函数
		2).全局指针指向全局变量
		3).语句块注入
			{
				extern 全局变量;
			}

C语言程序内存地址分布

在这里插入图片描述

关于程序内存地址的分布:
	一个程序(进程)有4G的虚拟内存地址空间
 	sizeof(指针) == 4 
	 0-3G   用户空间    	3G-4G   内核空间
	 从低地址到高地址: 用户空间(代码区->数据区->BSS->堆区->(堆栈缓冲区)->栈区)->内核空间
	 代码区: 存储代码文本、字面值神圣不可以修改,只要修改代码区的内容,会出现段错误(核心已转储
  	 数据区: 存储的是已经初始化的全局变量 和 已经初始化的静态变量
  	 BSS  : 存储的是未初始化的全局变量 和 未初始化的静态变量  自动清零  
      程序启动时会对该区域进行全部清零(擦除)
	  堆区: 动态内存(手动申请 手动释放)  从小到大扩张使用
	  栈区: 存储普通的局部变量和块变量,形参,函数调用时的开销,从大到小使用

	       一般来说,代码区、数据区、BSS程序运行之后,大小都是固定的,栈区和堆区是根据数据的多少在自由的扩张,
	  堆区从小到大扩张,栈区从大到小扩张,合理分配和使用内存,利用最大化。

今天先来讲讲关于堆区的内容:

堆区的动态内存,如果需要使用,需要自己申请,然后使用完之后手动释放。
#include<stdlib.h>
void *malloc(size_t size)
	申请的动态内存 size为申请的字节数
	返回值为void * 是一个万能指针,可以转换成任意类型的指针
	如果申请返回NULL,需要对申请的动态内存进行成功的判断。
	比如:
  4     int words(const char *s){
  5     if(s==NULL){
  6         return -1;
  7     }
  这里的if就是判断是否申请动态内存成功!
void free(void *ptr);
	释放动态内存
	一定要确保参数ptr为malloc/calloc/realloc返回的值。
	如果ptr前面的控制块被修改,将会导致核心段错误。
	即使释放掉所有动态内存,第一次申请的33页内存将一直会保留
	动态内存如果没有释放将造成内存泄露(这个问题很严重)。
	动态内存也不能够多次释放。
	
malloc虽然是申请size个字节的动态内存,但实际上确不是这个数字。
第一次malloc分配了至少33页的内存空间 1页=4096字节。
在该内存没有全部使用之前,不会再申请更多的内容(只是在之前申请的内存中划一部分出来)。
申请多少个字节的内容,严格控制使用多少个字节的内存,不要越界。

在这里插入图片描述

	动态内存:堆内存,手动申请,手动释放。
	内存泄露:申请的动态内存没有释放或者没有及时释放。
	内存碎片:多次申请和释放内容,会造成一些动态内存块中内存将无法使用。


	以下程序包括动态内存的申请,释放,以及一些需要注意的点,需要理解透彻:
#include <stdio.h>
  2 #include <stdlib.h>
  3 int main(){
  4     //100个整数
  5     int arr[100] = {};//栈区  arr  int *
  6 
  7     //int *p = malloc(0xffffffff);
  8     int *p = malloc(400);
  9     if(p==NULL){
 10         printf("malloc申请动态内存失败!\n");
 11         return -1;
 12     }
 13     //50 double 
 14         //malloc(50*8);
 15     int i = 0;
 16     for(;i<100;i++){
 17         p[i] = i;
 18     }
 19     p[50] = 9527;
 20     p[66] = 8888;
 21     for(i=0;i<100;i++){
 22         printf("%d ",p[i]);
 23     }
 24     printf("\n");
 25     double *pd = (double*)p;
 26     double d = 3.14;
 27     for(i=0;i<50;i++){
 28         pd[i] = d;
 29         d = d + 2.5;
 30     }
 31 
 32     for(i=0;i<50;i++){
 33         printf("%g ",pd[i]);
 34     }
 35     printf("\n");
 36     free(p);
 37 
 38     return 0;
 39 }

另外简单提一下calloc和realloc这两块内容

 void *calloc(size_t nmemb, size_t size);
 	申请nmemb个size字节大小的连续内存    总共nmemb*size个字节
 	等同于malloc(nmemb*size)
 	malloc申请的动态内存不一定会擦除内存中的数据
 	calloc一定会擦除
 	返回NULL表示失败

void *realloc(void *ptr, size_t size);
	ptr:必须是指向动态内存
	size: 想要最终调整为size个字节大小的动态内存,调整动态内存大小为size个字节。
#include <stdio.h>
  2 #include <stdlib.h>
  3 int main(){
  4     int *p = calloc(10,4);
  5     if(p==NULL){
  6         printf("calloc申请动态内存失败!\n");
  7         return -1;
  8     }
  9     size_t i;
 10     for(i=0;i<10;i++){
 11         *(p+i) = i*i;
 12     }
 13     printf("%p\n",p);
 14     int *p1 = malloc(4);
 15 
 16     p = realloc(p,20*4);//把p所指向的动态内存调整为80个字节
 17     printf("%p\n",p);
 18     for(i=0;i<20;i++){
 19         printf("%d ",p[i]);
 20     }
 21     printf("\n");
 22     free(p);
 23     p = NULL;
 24	return 0;
 25 	}
 	**注意:**
 		调整动态内存之后必须重新接收该函数的返回值,调整大小之后动态内存的位置可能发生变化,
 	如果在扩大的时候,后面的动态内存已经被使用了,那么将重新申请一块size个字节的动态内存然后把
 	之前内存中的数据拷贝过来,释放之前的动态内存。
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值