C语言5种存储区域
C语言5种存储区域
转发至:http://www.mamicode.com/info-detail-927635.html
系统为了管理内存 把内存划分了几个区域
1> 栈区
栈区之中的数据在栈区之中以栈的形式进行存储.
栈区的特点:数据是先进后出,
放在栈区里面存放的是局部变量.(例如定义在函数内部的变量)
栈区之中的数据(局部变量)的作用范围过了之后,系统就会回收自动管理栈区的内存(分配内存 , 回收内存),不需要开发人员来手动管理
2> 堆区
高效的使用内存
这里的内存可以由程序员自己手动管理 高效的使用内存 例如: 申请内存 释放内存.优化内存 ARC
申请内存的函数 malloc() memary alloc 申请内存空间
void *mallc(size_t);
函数名:malloc
返回值: void * (泛指针类型 可以轻松的转换为任意类型的指针)
返回一个指向新开辟的的存空间的首地址
类型是一个泛指针(可以根据接受者 动态的转换).
参数: size_t 申请动态空间的字节数的大小. 即:你要开辟多大的空间. 例如开辟一个整形的变量的存储空间(在堆区之中) malloc(4);
int *p = malloc(4);
释放内存的函数 free(p);// p 是你 刚刚使用 开辟空间函数返回的内存空间首地址的的指针接受者
最后还要将 p = NULL; 否则会出现野指针错误!
void *calloc(unsigned n,unsigned size);(10 * 4)
申请 count * size 个字节 count 是个数 size 是每一个占用的字节数
并且将申请到的内存之前的残留数据清空,效率比malloc 要低,但是更安全.
例如 :开辟十个整型数据的空间
int *p = calloc(10,sizeof(int));
void * realloc(<#void *#>, <#size_t#>); 重新分配内存空间.
realloc(p, size);
从指针p的位置 重新申请size个字节. 返回一个 泛类型的指针.
从p的位置开始申请,如果后面有size 个字节可以使用,就直接申请;如果没有,就去内存之中找一块连续的size字节,找到就直接申请,并且在申请之前,释放掉以前申请到的内存. 返回新的指针.
memset(void *,int ,size_t);
memset(p,c,n);
从指针的p的位置开始,初始化n个字节的内容并且把内容改为 C;
//memccpy(<#void *#>, <#const void *#>, <#int#>, <#size_t#>)
memccpy(dest, source, <#int#>, <#size_t#>)
memcpy(dest, source, n);
从指针source 的位置开始,向指针dest的位置,拷贝n个字节的内容.
3> 静态区(全局区)
静态区存放的是: 全局变量(定义在函数外部的变量 例如在主函数上面 定义的变量) 和 静态变量
static 类型的变量有什么特点:(只初始化一次(初始化是 在定义的时候辅助),不初始化的话,默认为零.)
静态区内存是由系统管理的.
一旦静态区的内存被分配, 静态区的内存直到程序全部结束之后才会被释放
4> 常量区
常量区存放: 常量(程序在运行的期间不能够被改变的量 例如: 10 ‘a‘ 1.12 "ios", 数组的名字)
常量区的内容是只能读的 不能被修改的的.
区别一下下面的代码:
char *p = "kpkoj";
等价于 char *p; p = "kpkoj";
此时char类型的指针p存放的是常量字符串的首地址 ("kpkoj"(存放在常量区)的首地址)
所以此时p指向的内容不能够被修改,只能被读取 即*p的值只能被读取,不能被修改.但是可以重新的将指针变量p指向新得地址.
例如在上面这个的操作的基础之上 在将p赋上新的值 p = "ddvdd";(拷贝的是地址此时又指向了一个新的常量的首地址)
这个情况: char str[] = "iOS";
这个是字符数组 是将常量字符串"iOS"的内容拷贝到栈区的字符数组之中 ,所以可以修改数组内的内容.例如: str[0]= ‘d‘;
但是str(数组名) 是一个常量的地址已经初始化,就不能被重定向(更改他的指向),所以只能通过下标或者什么的对其数组中的某个元素进行修改,区别上面的的指针情况.
常量的内存也是由系统管理的.
5> 代码区
内存还是由系统控制的
代码区的存放 :程序中的函数编译后cpu指令
代码区的地址:函数的地址,程序的入口地址.程序的名字.
栈区内存地址编号由高到低(栈区 -> 代码区).
// int *h = malloc(4);//开辟一个堆区的地址 大小为 4
// *h = 1024;//向堆区内存空间之中写入数据 1024
//
// printf("堆区的地址%p, %d\n" , h , *h);
// //在堆区之中 存入 "iphone 6s";
//
// char *ch = malloc(sizeof("iphone 6s"));
//// ch = "iphone 6s";
//// ch = "dddd";//这样只是将指针重新指向.而,新开辟的内存空间已经没有指向,造成内存没有指向 内存泄露
// strcpy(ch , "iphone 6s");//将常量区的内容拷贝到指向的刚刚开辟的内存区域!.
//// ch[0] = ‘1‘;//这里可以被修改 因为他指向的内存区域是栈区 不是 常量区域
//// ch = "iphone 6s";//指向常量区的地址.
//// ch[0] = ‘1‘;//这样就不能修改 ch[0]的内容 因为 ch指向的是一块常量地址,不能被修改. 上面已经有详细的阐述了.
// printf("%s \n" , ch);
//
//
//
// strcpy(ch, ch + 2);
// printf("%s\n",ch);
//
//
// int *p3 = malloc(4);
// printf("%p\n" , p3);//申请内存的堆区地址.
// printf("%p\n" , &p3);//指针变量的栈区的地址
//
// //同样的 开辟内存之后一定要记得释放 否则容易造成 内存泄露
// //内存泄露: 内存一直被占用 得不到释放.
// free(p3);//内存释放函数 free(开辟的内存的首地址) 只是将内存标记为可用而没有将里面的内容抹掉
// p3 = NULL;//记得安全的做法 将指针指向空 NULL 要不是就是野指针了.错误了
// // 使用动态内存分配的知识,在内存存放10个整数,随机数范围[2 , 399];
//
// int *open = malloc(sizeof(int) * 10);//分配一段连续的空间.
// int *lh = open;
// for (int i = 0; i < 10; i++)
// {
// *(open + i) = arc4random() % (399 - 2 + 1) + 2;//向下偏移就可以了,因为下面的也是开辟的动态内存空间 open++;
// open[i] = arc4random() % (399 - 2 + 1) + 2;
//
// printf("%d ",*(open + i));
// }
// printf("\n");
//
// BOOL flags = YES;
// int temp;
// for (int o = 0; o < 9 && flags; o++)
// {
// flags = NO;
// for (int i = 0; i < 9 - o; i++)
// {
// if (*(open + i) > *(open + 1 + i) )
// {
// temp = *(open + i);
// *(open + i) = *(open + 1 + i );
// *(open + i + 1) = temp;
// flags = YES;
// }
// }
// }
// for (int i = 0; i < 10; i++)
// {
// printf("%d " , open[i]);
// }
// printf("\n");
// free(open);
// open = NULL;
// const int b = 0;
// char *p = "iOS"; //定义了一个栈区的指针变量 存放着 常量区的地址.
//// p[0] = ‘f‘;
//// *p = ‘m‘;
// p = "ddd";
// puts(p);
// printf("常量去的地址%p \n",p);
// int a = 10;
// static int k = 20;//静态变量.
// printf("静态变量的地址 p %p\n" , &k);
// printf("静态区的地址:%p\n" , &b);
// printf("栈区的地址:%p\n" , &a);
// printf("代码区的地址:%p\n" , main);
// for(int i = 0 ; i < 100 ; i++ )
// {
//// int n = i;
//// static int n = 1; //只能被 定义和初始化一次. 存放在静态区 没有赋初值. 而且初始化的时候一定要 赋一个常量 不能赋值一个 变量.
//// printf("%d \n",n);
// }
// char ch[] = "jkjl3jo342pook25l414fe4op0kfe1";
// int i , sum;
// i = sum = 0;
// while (ch[i] != ‘\0‘)
// {
// if (ch[i] >= ‘0‘ && ch[i] <= ‘9‘)
// {
// sum++;
// }
// i++;
// }
// printf("%d\n\n" , sum);
// //数组定义的时候,元素的个数必须是确定的值 不能出现变量的不确定
// char *p = malloc(sum + 1);
// i = sum = 0;
// while (ch[i] != ‘\0‘)
// {
// if (ch[i] >= ‘0‘ && ch[i] <= ‘9‘)
// {
// *(p + sum) = ch[i];
// sum++;
// }
// i++;
// }
// p[sum] = ‘\0‘;
// printf("%s \n" , p);
// free(p);
// p = NULL;
// memccpy(<#void *#>, <#const void *#>, <#int#>, <#size_t#>)
// memcpy(<#void *#>, <#const void *#>, <#size_t#>)
// char *p = malloc(4);
// memset(p, 66, 2);
// printf("%s \n",p);
// char str1[] = "sdfsafdaf";
// char str2[] = "564545121";
// memcpy(str1, str2, 3);
// printf("%s \n" ,str1);
// memcmp(p1, p2, n);
// 内存的比较. 比较p1和p2 指向的内存之中的内容是否相等 ,比较n个字节的长度 相同的返回0,不同的返回差值.
// int *p1 = malloc(4);
// *p1 = 8 ;
// int *p2 = malloc(4);
// *p2 = 3;
// int result = memcmp(p1, p2, 1);
// printf("%d \n",result);
int *p1 , *p2;
p1 = malloc(3 * sizeof(int));
p2 = calloc(3 , sizeof(int));
memset(p1, 0, 3*sizeof(int));
for (int i = 0; i < 3; i++)
{
*(p1 + i) = arc4random()%(3 - 1 + 1) + 1;
*(p2 + i) = arc4random()%(3 - 1 + 1) + 1;
printf("%d %d",*(p1 + i),*(p2 + i));
// *(p1 + i) = 1;
// *(p2 + i) = 1;
printf("\n");
}
if (memcmp(p1, p2, 16)==0)
{
printf("good\n");
}
else
printf("Failed\n");
free(p1);
free(p2);
p1 = p2 = NULL;
C语言5种存储区域的更多相关文章
- C语言 内存四大存储区域
#include<stdio.h> #include<stdlib.h> //程序代码指令,define定义的常量---代码区(只读) //全局(关键)变量/常量,静态(关键) ...
- C语言_了解一下C语言中的四种存储类别
C语言是一门通用计算机编程语言,应用广泛.C语言的设计目标是提供一种能以简易的方式编译.处理低级存储器.产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言. C语言中的四种存储类别:auto ...
- 浅谈C语言的数据存储(一)
作者:冯老师,华清远见嵌入式学院讲师. 程序由指令和数据组成,C语言程序亦是如此.开发者在编写程序的时候往往需要根据不同数据的特点以及程序需求来选择不同的数据存储方式,那么在C语言中数据的存储分为哪些 ...
- 04 Storage and Calculation C语言中的存储和计算
文章内容来源于Programming Hub的学习记录,本人整理添加了中文翻译,如有侵权,联系本人删除 Variables C语言中的变量 Let's extend our mainfunction ...
- C/C++程序内存的各种变量存储区域和各个区域详解
转自 https://blog.csdn.net/jirryzhang/article/details/79518408 C语言在内存中一共分为如下几个区域,分别是: 1. 内存栈区: 存放局部变量名 ...
- Block存储区域
Block存储区域 首先,需要引入三个名词: ● _NSConcretStackBlock ● _NSConcretGlobalBlock ● _NSConcretMallocBlock 正如它们名字 ...
- 局部变量存储区域静态变量存储区域static变量存储区域
局部变量存储区域静态变量存储区域static变量存储区域 常见的存储区域可分为: 1.栈 由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区.里面的变量通常是局部变量.函数参数等. 2.堆 ...
- android开发中的5种存储数据方式
数据存储在开发中是使用最频繁的,根据不同的情况选择不同的存储数据方式对于提高开发效率很有帮助.下面笔者在主要介绍Android平台中实现数据存储的5种方式. 1.使用SharedPreferences ...
- 【C语言学习】存储类型
C语言中的存储类型主要有四种:auto.static.extern.register ★auto存储类型 默认的存储类型.在C语言中,假设忽略了变量的存储类型,那么编译器就会自己主动默认为auto型 ...
随机推荐
- Javascript调用 ActiveXObject导出excel文档。
function makeDataBook(){ var xls = new ActiveXObject ("Excel.Application"); xls.visible = ...
- linux配置使用外部smtp发送邮件
mail命令需要设定mail.rc(或nail.rc)文件, set from=user@domain.comset smtp=smtp.domain.comset smtp-auth-user=us ...
- zabbix metrics
http://blog.csdn.net/hengyunabc/article/details/44072285
- Python 协程/异步IO/Select\Poll\Epoll异步IO与事件驱动
1 Gevent 协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到 ...
- WPF中静态引用资源与动态引用资源的区别
WPF中静态引用资源与动态引用资源的区别 WPF中引用资源分为静态引用与动态引用,两者的区别在哪里呢?我们通过一个小的例子来理解. 点击“Update”按钮,第2个按钮的文字会变成“更上一层楼”, ...
- Debian 安装Nvidia显卡驱动
1.到nvidia官方网站下载自己显卡对应型号得驱动,如果不知道显卡型号,可以使用如下命令来查看 lspci | grep VGA 2.安装显卡驱动所必需得工具 apt-get install bui ...
- MVVM 入门介绍
转载自:http://www.objccn.io/issue-13-1/ 我于 2011 年在 500px 找到自己的第一份 iOS 开发工作.虽然我已经在大学里做了好几年 iOS 外包开发,但这才是 ...
- Android实现GIF图片解码与播放
Android实现GIF图片解码与播放 如何在Android中播放GIF图片呢?如果直接按以前的方法,分解图片,可能相对比较麻烦. 今天给大伙介绍一种新的方式,构造自己的Android图片解码帮助类, ...
- 给input元素添加float. 去除IE6 下input的空隙
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- java包(package)
为了更好地组织类,java提供了包机制,用于区别类名的命名空间. 这样在不同的命名空间就可以有相同命名的类. 1 把功能相似或相关的类或接口阻止在同一个包中,方便类的查找和使用. 2 如同文件夹一样, ...