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;

时间: 2024-10-19 01:55:55

C语言5种存储区域的相关文章

C语言笔记之存储类

在C语言中,一个数据对象(往往是指变量)可以由3种属性来描述:作用域,存储时期,链接.每种属性有不同的值,这些不同值的组合构成数据对象的存储模型,又称为存储类,即,一个数据对象如何存在于计算机中.以下描述中,我们以变量为例(另一个例子是函数)代表数据对象. 一.作用域 作用域属性描述了一个数据对象可以在(源代码的)哪些区域被访问,它有以下几个值:代码块.函数原型.文件. 1.文件作用域 函数是C源代码文件的基本组织单位,但是如果一个变量定义在所有函数之外,即没有在任何一个函数体内,那么该变量就具

C/C++程序内存的各种变量存储区域和各个区域详解

转自 https://blog.csdn.net/jirryzhang/article/details/79518408 C语言在内存中一共分为如下几个区域,分别是: 1. 内存栈区: 存放局部变量名:2. 内存堆区: 存放new或者malloc出来的对象:3. 常数区: 存放局部变量或者全局变量的值:4. 静态区: 用于存放全局变量或者静态变量:5. 代码区:二进制代码.知道如上一些内存分配机制,有助于我们理解指针的概念. C/C++不提供垃圾回收机制,因此需要对堆中的数据进行及时销毁,防止内

block存储区域——如何验证block在栈上,还是堆上

block存储区域 这就需要引入三个名词: ● _NSConcretStackBlock ● _NSConcretGlobalBlock ● _NSConcretMallocBlock 正如它们名字说的那样,说明了block的三种存储方式:栈.全局.堆. [要点1]定义在函数外面的block是global的:另外如果函数内部的block,但是没有捕获任何自动变量,那么它也是全局的.比如下面这样的代码: typedef int (^blk_t)(int); for(...){ blk_t blk

Android中常用的三种存储方法浅析

Android中常用的三种存储方法浅析 Android中数据存储有5种方式: [1]使用SharedPreferences存储数据 [2]文件存储数据 [3]SQLite数据库存储数据 [4]使用ContentProvider存储数据 [5]网络存储数据 在这里我只总结了三种我用到过的或即将可能用到的三种存储方法. 一.使用SharedPreferences存储数据 SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置信息比如窗口状态,它的本质是基

数据结构的几种存储方式

              数据的存储结构是数据结构的一个重要内容.在计算机中,数据的存储结构可以采取如下四中方法来表现. 1)           顺序存储方式 简单的说,顺序存储方式就是在一块连续的存储区域 一个接着一个的存放数据.顺序存储方式把逻辑上相连的结点存储在物理位置上相邻的存储单元里,结点间的逻辑关系由存储单元的邻接挂安息来体现.顺序存储方式也称为顺序存储结构(sequentialstorage structure),一般采用数组或者结构数组来描述.               线

常见的三种存储技术以及iSCSI协议

1.常见的存储技术 DAS:Direct  Attached Storage,直接附加存储,存储设备通过SCSI接口电缆直接连接到服务器的,存储设备不带有任何操作系统.它依赖于服务器,存储设备就是将硬件设备堆叠起来的.DAS也可称为SAS(Server Attached storage,即服务器附加存储). DAS具有如下特性: 1.DAS设备不带有任何操作系统,文件系统位于服务器端,因此是以块级别进行数据传输 2.它是通过SCSI接口电缆与服务器相连,因此,会增加服务器的I/O操作,占用cpu

存储区域

前言:类型定义后,存储在哪里?变量定义后存储在哪里?程序代码存储在哪里? 1. 全局数据区和程序代码区 类型定义后,存在内存的只读区域,不可见,无法取得地址.类变量记录的是地址偏移,与对象绑定才能取得地址. 变量: 全局变量存在全局数据区,全局静态变量存在全局数据区的全局静态变量段.(两者相临或相差几个字节). 名空间变量存在全局数据区,和全局变量同一存储区域,名空间静态变量存在全局数据区的名空间静态变量段,和全局静态变量同一存储区域. 类变量名称列表中记录的是地址偏移,和对象绑定才能取得地址.

【C语言学习】存储类型

C语言中的存储类型主要有四种:auto.static.extern.register ★auto存储类型 默认的存储类型.在C语言中,如果忽略了变量的存储类型,那么编译器就会自动默认为auto型 ★register存储类型 寄存器变量.寄存器位于CPU,它的特点是:容量小.速度快.它一般用来暂存程序中使用频繁的变量.或者一些中间变量等,能提高程序的执行速度.此类别的变量会优先分配寄存器. ★static存储类型 static定义的变量都是静态变量,用于限制作用域,无论是全局变量还是局部变量都存储

java数据的5种存储位置(转)

任何语言所编写的程序,其中的各类型的数据都需要一个存储位置,java中书的存储位置分为以下5种: 1.寄存器 最快的存储区,位于处理器内部,但是数量及其有限.所以寄存器根据需求自动分配,无序人为控制. 2.栈内存 位于RAM中,通过堆栈指针可以从处理器中获得直接支持.堆栈指针向下移动,则分配新的内存:向上移动,则释放哪些内存.这种存储方式仅次于寄存器.(常用于存放对象引用和基本数据类型,而不用于存储对象) 3.堆 一种通用的内存池,也位于RAM中.其中存放的数据由JVM自动进行管理. 堆相对于栈