【学习ios之路:C语言】存储区内存划分

一. 内存存储区的划分:

1.栈区:栈区主要存放函数内部定义的变量,数组.函数调用时,开辟空间,函数执行完毕,回收空间,空间的开辟与回收有系统管理.

2.堆区:堆区最大的特点:空间的开辟与释放有开发人员手动管理.

3.全局区静态区:主要存放函数外部定义的全局变量以及静态变量,空间一旦开辟,就不会回收.直到应用程序执行结束.

4.常量区:存储常量.1.整形常量.2.浮点型常量.3,字符串常量.4.字符串常量.

5.代码区:存放程序编译之后生成的cpu指令.

二.malloc,在堆区开辟空间.

    //在堆区开辟空间.
    //void * 泛型:可以代表所有的指针类型.
    //如果要存储两个整数,用int * ,存储8个字符,用char * ,存储4个人整数,用short *.
    //malloc 在堆区开辟n个字节大小的空间,返回空间的首地址.
    char *p = malloc(8);
    //存储iphone
    strcpy(p, "iphome");
    printf("%s\n",p);//iphome
    //释放空间
    //删除只是标记删除,不会清楚空间上的内容.
    free(p); p = NULL;

三.堆区空间问题.

1.野指针问题:访问没有所有权的空间.

2.过度释放:一块空间释放多次,程序会立即crash.

3.内存泄露:空间没有释放,造成内存堆积.不会造成立即crash,安全隐患.

处理方法 : p = NULL;

使用指针必备条件:       1.指针要由明确的指向.

2.指向一个可以控制的区域

四.malloc应用

1.一个有5个元素的数组空间.存储5个整数.

    int  *p = malloc(sizeof(int)*5);
    for (int i = 0; i < 5; i++) {
        p[i] = arc4random() % (40 - 20 + 1) + 20;
        printf("%d ",p[i]);
    }
    printf("\n");

   //排序
    for (int i = 0; i < 5 - 1; i++) {
        for (int j = 0; j < 5 - 1 - i; j++) {
            if (p[j] > p[j + 1]) {
                int temp = p[j];
                p[j] = p[j + 1];
                p[j + 1] = temp;
            }
        }
    }
    for (int i = 0; i < 5; i++) {
        printf("%d ",p[i]);
    }

    free(p);
    p = NULL;

2.有一个字符串,其中包含数字,提取其中的数字,要求动态分配内存保存.

    printf("请输入一段字符串:\n");
    char str[] = {0};
    scanf("%s",str);
    int i = 0;
    int num = 0;
    while (str[i] != '\0') {
        if (str[i] >= '0' && str[i] <= '9') {
            num++;
        }
        i++;
    }
    char *q = malloc(sizeof(char)*(num+1));//根据长度生成空间 num + 1 字符串隐藏\0
    int m = 0,n = 0;
    for (int i = 0; i < num; i++) {
        while (str[m] != '\0') {
            if (str[m] >= '0' && str[m] <= '9') {
                q[n] = str[m];
                n++;
            }
            m++;
        }
    }
    q[n] = '\0';//多出来的存储\0
    printf("\n");
    for (int i = 0; i < num; i++) {
        printf("%c", q[i] );
    }
    free(q);
    q = NULL;

3.输入3个学员的姓名,动态分配内存保存学员姓名,并在最后输出.


    char *names[3] = {0}; //存储在堆区开辟的空间的首地址.
    char temp[255] = {0};//存储从控制台输入的字符串
    for (int i = 0; i < 3; i++) {
        printf("请输入3个学生的姓名");
        scanf("%s", temp);//输入到temp临时数组中.
        //动态计算输入的字符串的长度
        unsigned long length = strlen(temp);
        //在堆区开辟空间.
        names[i] = malloc(length + 1);//将堆区空间的地址存储指针数组中,
         //将内容拷贝到堆区.
        strcpy(names[i], temp);

    }

    for (int i = 0; i < 3; i++) {
        printf("%s \n",names[i]);
        free(names[i]);<span style="font-family: Arial, Helvetica, sans-serif;">//空间的释放</span>
        names[i] = NULL;

    }

(2)calloc用法


    1.void * calloc(unsigned n, unsigned size);
    分配n个size大小的空间.并且把该内存上的所有字节清零.
    int *p = calloc(5, 4);//分配5块大小为4字节的空间,并且做清零操作.

    free(p);
    p = NULL;

(3)realloc 用法


    void *realloc(void *p,unsigned newSize);
    int *p = malloc(10);
    printf("%p\n",p);
    int *q = realloc(p, 40);//重新分配一个大小为100 的空间.
    //realloc 返回当前空间的首地址.如果当前空间不够,则在另一块申请20个字节的空间,此时返回新的空间的地址.
    printf("%p\n",q);
    free(q);
    q = NULL;
    p = NULL;//不需要释放.

(4)memcpy用法


  void *memcpy (void *dest, const void *source, size_t n);
      //从source指向内存开始拷贝到dest中n个字节.

     char *p1 = malloc(8);
     char *p2 = malloc(8);

     strcpy(p2, "frank");
     printf("%s\n", p2);
     //memcpy(p1, p2, 6);

     memcpy(p1, p2, 4);
     memcpy(p1, p2 + 2, 4);//ank
     p1[4] = '\0';
     printf("%s\n", p1);//fran

(5)memset用法

<pre name="code" class="cpp">4. void * memset(void *s, int c, size_t n);
    //从s指向的内存开始初始化n个字节的内容为c
    char *p1 = malloc(8);
    memset(p1,0,8);

五.练习

定义两个整型指针,分别用malloc、calloc对其分配空间保存3个元素,malloc分配的空间用memset清零,随机对数组进行赋值随机范围1-3,赋值后用memcmp比较两个数组。如果相同打印Good!否则打印Failed..

    int *p = malloc(sizeof(int) * 3);
    int *q = calloc(3, sizeof(int));
    memset(p, 0, sizeof(int) * 3);
    for (int i = 0;i < 3;i++) {
        p[i] = arc4random() % (3 - 1 + 1) + 1;
        q[i] = arc4random() % (3 - 1 + 1) + 1;
        printf("p:%d q:%d\n",p[i],q[i]);
    }

   //比较buf1和buf2指向的内存是否相同,比较count个字节
        if(memcmp(p , q , sizeof(int) * 3) == 0){ //地址 .3即3个字节.
            printf("profect\n");
        } else {
            printf("failed\n");
        }

    free(p);
    free(q);
    p = NULL;
    q = NULL;

六.宏

定义宏:
三部分:1.#define 2.宏名 3. 替换的内容

宏的作用:
只做替换.

宏名的命名规范: 1.全部大写 2. k+驼峰

无参宏  #define kArrayNumber5     #define N
10

有参宏  #define MUL(A,B) ((A) * (B))

宏应该注意的几个问题.

1.宏名大写

2.参数一定要加小括号.

3.宏替换的内容不要加分号.

4.对于有参宏,宏名一与参数之间不要加空格.

七.枚举

定义枚举

枚举的作用 :罗列出所有的可能性

枚举是将人能够识别的标示符和计算机能够识别的数字结合在一起.

例子:

//定义枚举
typedef enum button {
    //通过1的每一位来表示一个状态.
    Close = 1 << 0,//关闭 001    第一位1表示关闭
    Max = 1 << 1, // 最大化 010   第二位为1表示最大化
    Min = 1 << 2//最小化 100      第三位为1表示最小化

}Button;
   如果想宝贝多个枚举值,按位或即可,前提是枚举值通过左移符号对应值.
   BOOL b = Close | Max | Min; //001 010 100 = 111
   printf("%d\n", b);

八.条件编译

以#开头的叫做预编译指令

预编译指令做一些文本以及代码的替换工作.

形式1:

#define A
#ifdef A
    int a = 10;//条件编译(根据条件编译不同的代码)
#else
    int a = 20;
#endif
    printf("%d ", a);//10

形式2:

#define A
#ifndef A //如果没有定义
    int a = 10;//条件编译(根据条件编译不同的代码)
#else
    int a = 20;
#endif
    printf("%d\n",a);//20

形式3:

# if  10 //非0即为真,执行if,否则为假,执行else
    int a = 10;
#else
    int b = 20;
#endif
    printf("%d\n", a); //10

九.面试题 #include 与 #import
的区别

#import 相比 #include 能够防止重复导入,引起交叉编译.

#import " " 导入自定义的头文件

#impoer <> 导入系统的头文件

时间: 2024-10-26 19:05:28

【学习ios之路:C语言】存储区内存划分的相关文章

【学习ios之路:C语言】总结整理:学好Object-C---C语言必备知识点

一.基本数据类型.常量.变量.运算符 1.数据类型 int. short.char.long.float.double. 2.常量的分类.(1).整型常量 (2)浮点型常量 (3)字符常量 (4)字符串常量. 3.常量的特性:常量存储在常量区,常量区的内容不可被更改. 4.变量的定义与本质.数据类型 变量名 = 初值 . 本质变量就是一个容器. 5.变量名的命名规范 6.运算符. (1)赋值运算符 = (2)算数运算符 +  -  *  /  %  ++  -- (3)复合运算符  +=  -+

【学习ios之路:C语言】指针

指针 1.指针定义,即简单用法. <span style="font-size:14px;"> //指针变量:专门用来存储地址的变量. int *p = NULL;//NULL == 0 /** * 变量定义时: * (int *):指针类型 * p: 变量名 NULL:初始值. * NULL(指向了一个无效的区域) * *的作用: 告诉编译器,后面变量是指针变量,用来存储地址. * int作用: 1.当通过指针变量取数据时,一次性读取几个字节的数据. 2.当指针变量+1时

【学习ios之路:C语言】一维数组,数组排序,字符数组

1.数组 数组,快速定义多个变量. 数组定义: 数据类型 数组名[数组元素的个数] = {值1, 值2, 值 3}; 数组所占存储空间大小 = 数组元素个数 * 每个元素所占的存储空间大小. %lu  unsigned long 无符号的长整型. 无符号 >=0 sizeof 存储大小值  //用来计算一个变量,类型,以及数组所占存储空间的大小. int a[5] = { 2, 7, 4, 3, 6 };  printf("%lu\n", sizeof(arr)); //5 in

【学习ios之路:C语言】②高级指针应用

1.指针与字符数组 <span style="font-size:14px;"> /** 定义字符串的2种方式 * 1.利用数组 * char name[] = "itcast" * *特点:字符串里面的字符是可以修改的 * *使用场合:字符串的内容需要经常修改. * 2.利用指针 * char *name = "itcast"; * *特点:字符串其实是一个常量字符串,里面的字符是不能修改的; * *使用场合:字符串内容不需要修改,

【学习ios之路:C语言】进制.位运算.栈

1.进制转换 1).10进制转为N进制.方法:(连除倒取余). 2).N进制转换为10进制.方法:(按权求和法):当前位上的数乘以基数的位数减1次方. 例: 0b1111 ---- 1* 2^3 + 1*2^2 +1 * 2^1 +1*2^0 = 15; 038 ----- 3*16^1 +8*16^0 = 56; 3).N进制转换N进制. 例如: 二进制 --- 16进制 1010   0011  ----  A 3 1111   0011  ----  F 3 int a = 010;//8

【学习ios之路:C语言】小程序:实现类似ATM取款机功能.

小程序:模拟ATM机取款的过程 1).定义两个能保存5个整形数的数组,一个用于保存5个人的卡号,一个用于保存对应卡号的密码 2).判断输入的卡号是否在数组中. 3).如果在数组中就让输入密码,判断是否和卡号对应的密码匹配. 4).判断密码,24小时内只允许输入3次错误的密码.输入错误应该提示还剩下的输入次数,3次都输入错误提示24小时内不允许操作该卡. 5).密码正确就让用户对该账户进行相应的操作. 6).注意取款的限制. 7).述功能对于一个ATM机是循环的过程,也就是说每个客户都会按照上面的

【学习ios之路:C语言】函数及递归的简单应用

函数定义: 返回值类型 函数名(形参列表){函数体(函数的实现内容)}; 函数定义的四种形式: //函数定义第一种形式: 无参数, 无返回值 void byMilk() { //如果没有参数,小括号必不可少. printf("没钱\n"); } //函数名的命名规范:由多个英文单词组成,除了第一个单词的首字母小写,其余单词首字母大写. //函数定义第二种形式,有返回值,无参数 float salary() { printf("同志们辛苦了\n"); return 0

【学习ios之路:C语言】循环方面试题

1.打印出如下所示图形  : * *  * * * * 代码如下: for (int i = 0; i < 3; i++) { for (int j = 2; j > i; j--) { printf(" "); } for (int k = 0; k < i + 1; k++) { printf(" *"); } printf("\n"); } 2. 打印出如下图形: * *   * *  *  * *   * * 代码如下:

【学习ios之路:C语言】C语言中容易出错的试题整理.

注:此类题都是比较基础的试题,但是都容易让人忽视,或者平常不在意的. 1.表达式3.6-5/2+1.2+5%2的值是(D). A. 4.3  B. 4.8  C.3.3  D. 3.8 2.设有说明:char w;int x;float y;double z;则表达式w*x+z-y值的数据类型为:(D) A. float   B. char  C. int  D. double 3.以下关于运算符优先顺序的描述中正确的是:(C) A.关系运算符<算术运算符<赋值运算符<逻辑与运算符