iOS开发学习之C语言---C09 动态内存分配

来源:互联网 发布:excle怎么做数据分析 编辑:程序博客网 时间:2024/05/17 21:56

//

//  main.m

//  C09 动态内存分配

//

//  Created by 康亮亮 on 15/10/19.

//  Copyright (c) 2015 Darling.com. All rights reserved.

//


#import <Foundation/Foundation.h>

// 静态变量(全局变量)

// d的在整个工程中都有效

int d =12;

// e的作用只在当前文件中

static int e = 23;



void testMemory(){

    printf("hello");

    

}






int main(int argc,const char * argv[]) {

    // 按地址从高到低

    //栈内存中返回地址是不安全的,要避免!先进后出,局部变量丢在栈区

    //堆区,手动分配,手动释放!

    //静态存储区 全局变量(不属于任何一个函数)丢在静态存储区

    //常量占用内存,只读状态,不可修改!

    // 代码区

    

    

#pragma mark 内存五大区

   /*

     1、内存地址按照从高到低可以分为五个区域,每个区域用来存放不同类型的数据

     2、五大区域按地址从高到低:栈区、堆区、静态区、常量区、代码区。

     */

    

    //打印各个区的地址

    // 1、栈区的地址

    //    int a = 23;

    //    printf("栈区的地址是:%p\n",&a);

    //    // 2、堆区的地址

    //    int *p = malloc(4);

    //    printf("堆区的地址是:%p\n",p);

    //    // 3、静态区的地址

    //    static int b = 12;

    //    printf("静态区的地址是:%p\n",&b);

    //    // 4、常量区的地址

    //    char *p1 = "hello";

    //    printf("常量区的地址是:%p\n",p1);

    //    // 5、代码区的地址

    //    printf("代码区的地址是:%p\n",testMemory);

    

    

    

#pragma mark 栈区

   /*

     1、局部变量的存储空间,基本都是在栈区。局部变量在函数、循环、分支中定义。

     2、栈区的内存由系统负责分配和回收,按照从高到低分配内存空间。在存储数据时,从低到高存储数据。

     3、栈区里的内存,会在变量出了作用域后自动被系统回收。

     4、栈的数据结构:先进后出(FILO),最先入栈的数据,会保存在栈底。(例如:手枪的弹夹)

     5、栈区会存在数据稳定性的问题:在函数中返回栈的内存地址是不安全的,因为那块地址被系统回收了,随时会被其他数据占用。

     */

    

    

    

#pragma mark 静态区的特点

   /*

     1、全局变量,使用static修饰的变量(或局部变量)都存储在静态区

     2、静态区的存储空间由系统分配和回收。

     3、程序运行结束后,静态区的存储空间才会被回收。静态去变量的生命周期和程序的生命周期一样长。

     4、静态区的变量只能初始化一次,在编译期进行初始化,在程序运行期,可以修改静态区变量的值。

     5、静态变量如果没有设置初始值,默认设置为0

     6、如果变量是一个局部变量,使用static修饰之后,变量的作用域不会发生改变。我们可以使用指针指向这块地址,这样在作用域之外就能正常访问它的值了。(因为静态区的变量,生命周期和程序运行的生命周期一样长)

     */

    //    int *p3 = NULL;

    //    for (int i = 0; i < 5; i++) {

    //        static int f = 34; // f从栈区挪到了静态区,在编译期,进行初始化,程序在运行时就不再执行这条代码

    //        f = 22; // 在运行期改值

    //        p3 = &f;

    //    }

    

    

    

    

#pragma mark 常量区(文字常量区)

   /*

     1、常量存储在常量区。如:常量字符串

     2、常量区的内存由系统分配和回收

     3、在程序执行结束后,常量区的内存空间才会被回收

     4、常量区的数据只能被读取,不能被修改,修改会造成程序崩溃

     */

    //    char *p4 = "nice";

    //    p4[0] = 'a'; // 程序运行到这一行会崩溃,因为修改了常量区的内容

    

    

    

    

#pragma mark 代码区

   /*

     1、内存由系统分配和回收

     2、程序运行结束后,由系统回收分配过的存储空间

     3、代码区只能读取,不能修改

     4、编程语言被翻译为机器指令后就存放在代码区

     */

    

    

    

    

    

#pragma mark 堆区

   /*

     1、由开发者负责分配和回收

     2、如果只开辟,不回收的话,会造成内存泄露

     3、堆区的内存如果程序员不回收的话,在程序执行结束后,系统会帮忙回收,但是如果程序员不能及时清理内存,那么程序运行期间可能会因为内存泄露造成堆内存被全部占用,程序无法继续运行。

     */

    

    

    // 内存分配函数malloc

    // void *malloc(size);

    // void *:表示的是无类型指针,这种指针可以转化为任何类型指针(返回值可以被任何类型的指针保存)

    // malloc:内存分配函数名

    // size:函数参数,是一个无符号整形数,表示要在堆区中开辟的字节个数

    //这个函数的作用是:在堆区开辟指定size字节数的内存,并将内存首地址返回

    

    

    //    // 定义一个整形指针

    //    int *p = NULL;

    //    // 使用函数在堆区中开辟5int类型的字节数

    //    p = malloc( sizeof(int) * 5 );

    //    // 将前四个字节里放入23

    //    *p = 23;

    //    // 下一个数字是44

    //    *(p+1) = 44;

    //    //打印存进去的两个数,及其地址

    //    printf("%d\n%p\n%d\n%p\n", *p, p, *(p+1), p+1);

    

    

    

    //练习: 分配内存,用来存储float类型的数,12.34并打印输出

    

    //    float *p = NULL;

    //    p = malloc( sizeof(float) );

   //

    //    *p = 12.34;

    //    printf("%f\n%p\n", *p, p);

    

    

    

    

    // 释放指针 ·

    //    int *p = malloc(sizeof(int));

    //    *p = 12;

    //    // 使用free函数,释放指针指向的内存空间

    //    free(p);

    ////    printf("*p = %d\n", *p);

   //

    //    int *q = malloc(sizeof(int));

    //    *q = 45;

    //    printf("%p,%p\n", p, q);

    //    free(q);

    //    q = NULL; //在指向的内存空间被释放后,应该将该指针指向0x0的位置,防止产生野指针的现象

    ////    free(q); // 此时造成了过度释放:对一个已经释放的区域再次释放

    

    

    

    

    

    

    

   //

    //    int *p1 = NULL;

    //    p1 = malloc(sizeof(int) * 5); //sizeof(int) * 5 = 20

    //    for (int i = 0; i < 5; i++) {

    //        *p1 = i;

    //        p1++;

    //    }

   //

    //    //如果程序在这里就结束,就产生了内存泄露

   //

    //    //首先要将指针挪到这片地址空间起始地址

    //    for (int i = 0; i < 5; i++) {

    //        p1--;

    //    }

   //

    //    //在这里释放内存空间,字节数就是当初分配给p1指针访问的字节数(在这里是20个字节)

    //    free(p1);

   //

    //    p1 = NULL;

    

    

    

    

    

    //练习1: 有一字符串,其中包含数字,提取其中的数字.要求动态分配内存保存提示: 先计算出有几个数字,然后根据数字的个数来开辟空间.

    //    char string[] = "hey1ha2wu9";

    //    // 1.查找字符串中数字字符的个数

    //    // 1.1定义一个计数器,记录字符串中数字的个数

    //    int count = 0;

    //    // 1.2 使用循环来遍历字符串,找到数字字符

    //    for (int i = 0; i < strlen(string); i++) {

    //        // 1.2.1 判断当前字符是否是0~9之间的字符

    //        if ('0' <= string[i] && string[i] <= '9') {

    //            count++;     // 符合判断条件,则让计数器加一

    //        }

    //    }

    //    // 打印验证

    //    printf("count = %d\n", count);

   //

    //    // 2.开辟堆内存的空间,并将数字字符转换为整形数,存进去

    //    // 2.1 开辟堆内存中的空间

    //    int *p8 = malloc(sizeof(int) * count);

    //    // 2.2 使用循环将数字存进堆内存

    //    int num = 0;  //这个变量是给指针偏移使用的,在每找到一个数字后,就将(p+num)这个指针向后偏移的

    //    for (int i = 0; i < strlen(string); i++) {

    //        // 判断找出数字字符

    //        if ('0' <= string[i] && string[i] <= '9') {

    //            // 将数字字符转换为整形数

    //            int temp = string[i] - '0';

    //            printf("temp = %d\n", temp);

    //            // int类型的数字存进堆内存中

    //            *(p8 + num) = temp; //(p8 + num)

    //            num++;

   //

    //        }

    //    }

   //

    //    // 打印存进堆内存中的数据

    //    for (int i = 0; i < count; i++) {

    //        int a = *(p8 + i); // (p+i)是个新指针,不建议用(p++

    //        printf("%d\n",a);

    //    }

   //

    //    // 释放内存空间

    //    free(p8);

    

    

#pragma mark  callocrealloc

   /*

     calloc(<#size_t#>, <#size_t#>)

     1、前一个参数表示n个单位,后一个参数表示一单位是几个字节(size)。开辟的总长度就是n*size个字节数

     2、该函数会将开辟出来的内存空间清零

     3、效率问题:由于会自动清零,所以calloc函数的执行效率低于malloc

     */

    

    //    // 在堆区开辟10个字节的空间,使用calloc

    //    char *str = NULL;

    //    str = calloc(2, 5);

    //    // “Hello”写入堆内存中

    //    strcpy(str, "hello");

    //    printf("%s\n", str);

    //    printf("%d\n", *(str + 8));

    //    free(str);

    //    str = NULL;

    

    

    

    

   /*

     realloc(<#void *#>, <#size_t#>)

     1、第一个参数是指针,已有的内存空间的首地址(需要扩充内存字节数的空间的首地址)。第二个参数是:重新给这个指针指向的地址分配多少字节

     

     2、如果原空间足够大,则在原空间基础上重新分配;如果原空间不够大,就会重新寻找一块连续的存储空间(能够分配新的字节个数),重新分配,之前保存在内存中的数据会被原样拷贝到新空间里。

     */

    //    int *p7 = malloc(10);

    //    printf("p7 = %p\n", p7);

    //    int *q7 = malloc(4);

   //

    //    p7 = realloc(p7, 40);

    //    printf("p7 = %p\n", p7);

    //    free(p7);  //虽然p7的指向发生改变,但是在改变之前,系统就代替程序员将它原来指向的区域释放掉,在这里,我们只需要释放新指向的区域即可。

    //    free(q7);

    

    

    

#pragma mark 内存操作函数

   /*

     memset(<#void *#>, <#int#>, <#size_t#>)

     三个参数,第一个是指针p,第二个是整型n,第三个长度size

     这个函数的作用是:从给定的地址开始一直向后size个字节数,这个范围的内存的值被设置为n

     */

    

    //开辟5int类型的空间,使用memset函数将这五个字节的空间初始化为3

    //    int *p = malloc(5 * sizeof(int));

    //    // 使用初始化函数设置初始值

    //    memset(p, 3, 5);    // 最后一个参数表示的是初始化几个字节

    //    printf("*p = %d\n", *p);

    //    printf("*p = %d\n", p[0]);

    

    

    

   /*

     memcpy(<#void *#>, <#const void *#>, <#size_t#>)

     1、前两个参数是指针类型,最后一个参数是整型,表示范围size

     2、将第二个指针指向的地址开始,连续拷贝size个字节的内容到第一个指针指向的空间中

     3、第一个指针指向的空间字节必须大于等于size

     */

    //    char *p1 = malloc(3);

    //    p1 = "ab";

   //

    //    char *p2 = malloc(3);

    //    memcpy(p1, p2, 1);

    //    printf("%s\n", p1);

    

    

    

   /*

     * 我们可以使用memcpy函数来操作堆区的内存空间

     */

    //    char wrongName[] = "bj123";

    //    char rightName[] = "bj234";

    //    memcpy(wrongName, rightName, 3);  //rightName指向的地址开始连续3个字节的内容拷贝到wrongName中。(这里操作的是栈区的内存)

    //    printf("%s\n", wrongName);

    

    

   /*

     memcmp(<#const void *#>, <#const void *#>, <#size_t#>)

     字符串比较函数:参数是两个指针,从这两个指针指向的位置开始,一直比较size个字节,并将比较结果返回

     

     */

    

    //    int num1[3] = {1, 4, 3};

    //    int num2[3] = {1, 2, 3};

    //    int result = memcmp(num1, num2, 3); //比较的是字节数,并不是元素的个数

    //    printf("result = %d\n", result);

    

    

    

    

   return 0;

}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝顾客给差评怎么办 淘宝买家账号体检违规怎么办 买家淘宝账户体检中心违规怎么办 淘宝卖家电话骚扰该怎么办 手机欠费销户了怎么办 想下载好多个淘宝怎么办 送快递不记得路怎么办 淘宝物流弄丢了怎么办 邮政快递碰上难缠客户怎么办 举证工伤对方不签收怎么办 快递员收件的钱怎么办 锐捷网卡是空的怎么办 mac系统excel太慢怎么办 二手车交易发票丢了怎么办 转转上买二手电脑被骗了怎么办 如果电脑买贵了怎么办 电脑配置低玩lol卡怎么办 电视打开显示无信号怎么办 电脑卡怎么办换个驱动 刚开始开淘宝店没人买怎么办 公司有人带自己电脑办公怎么办 组装电脑连不上网怎么办 显卡玩不起吃鸡怎么办 u盘内存是假的怎么办 新买的电脑应该怎么办 海尔一体机电脑开不开机怎么办 苹果笔记本系统坏了怎么办 苹果笔记本电脑电池坏了怎么办 苹果笔记本电脑屏幕坏了怎么办 平板开关键坏了怎么办 平板电脑电池坏了怎么办 平板电脑充电口坏了怎么办 平板电脑系统坏了怎么办 平板电脑充电器坏了怎么办 平板电脑触摸屏坏了怎么办 平板电脑关不了机怎么办 平板电脑触摸屏没反应怎么办 平板电脑声音太小怎么办 平板电脑频碎了怎么办? 淘宝直播展示频道排后怎么办 网店头像改不了怎么办