zoukankan      html  css  js  c++  java
  • C语言回顾-内存管理和指针函数

    1.fgets()函数

    该函数是一个文件操作相关的函数

    暂时使用这个函数可以从键盘上接收一个字符串,保存到数组中

    char str[50];

    1)scanf("%s",str);//缺点:不能接收空格,也是不安全的

    2)gets(str);//优点:可以接收空格

            //缺点:会有一个警告,不安全的,比如数组的长度是50,我们输入的字符大于等于50的时候,会把50个字符全部放到数组中

            //没有空间存放字符串结束符

    3)fgets是一个安全的字符串接收函数,比如数组的长度是50,我们输入的字符大于等于50的时候,会把前49个字符全部放到数组中,最后一个位置存放

    使用格式:char *fgets(char *s,int n,FILE *fp);

    fgets(数组名,数组长度,stdin);

    当输入的字符串的长度小于数组长度的时候,fgets还会接收回车,回车后才是

    2.fputs()函数

    格式:fputs(数组名,stdout);

    不会自动换行,也不能进行格式化输出

    puts有换行

    //
    //  main.c
    //  Fgets
    //
    //  Created by fanyafang on 15/11/5.
    //  Copyright © 2015年 itcast. All rights reserved.
    //
    
    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, const char * argv[]) {
        char str[5];
        fgets(str,sizeof(str),stdin);
        //把字符串后面的
    改为
        //if(str[strlen(str)-1]=='
    ') str[strlen(str)-1]='';
        printf("---->%s
    ",str);
        
        puts(str);//有换行
        fputs(str,stdout);//无换行
        return 0;
    }

    3.const类型修饰符

    常类型是指使用类型修饰符const说明的类型,常类型的变量或者对象的值是不能被更新的

    1)修饰变量可以让变量的值不能改变

    2)修饰指针变量,const在*的左侧,那么变量值不能改变;如果在* 的右侧,表示指向不能改变;如果在* 的两侧,表示两个都不能变

    //
    //  main.c
    //  const使用
    //
    //  Created by fanyafang on 15/11/5.
    //  Copyright © 2015年 itcast. All rights reserved.
    //
    
    #include <stdio.h>
    
    int main(int argc, const char * argv[]) {
        //1)修饰变量
        const int a=10;
        printf("%d
    ",a);
        //a=34;报错,不能修改
        //2)用指针强制修改变量
        int *p=&a;
        *p=100;
        printf("%d
    ",a);//值不一样
        printf("%d
    ",*p);
        printf("%p
    ",&a);//地址一样
        printf("%p
    ",p);
        //3)修饰指针变量,指向可以改变,指向的值不可以改变
        int b=100;
        const int *p1=&a;
        p1=&b;
        
        int const *p6=&a;
        p1=&b;
        
        //4)const修饰的指针变量,指针变量指向的变量值可以变,指向不能变
        int * const p3=&a;
        *p3=1000;//指向的值可以变
        //ps=&b;报错,指向不能变
        //5)const修饰的指针变量,变量值和指向都不能变
        const int * const p4=&a;
        //*p4=12000;
        //p4=&b;
        
        return 0;
    }

    3.内存管理

    1)内存分配方式

    1))静态分配,在程序编译的适合就已经分配好,这块内存在程序的整个运行期都存在,例如全局变量,static变量

    2))在栈上创建,在执行函数时,函数内局部变量的存储单元,效率很高,容量有限

    3))从堆上分配,议程动态内存分配,程序在运行的时候用malloc或new申请任意多少的内存,手动用free或delete释放内存,灵活

    2)内存分区

    栈:运行时分配,局部变量

    堆:运行时分配

    BSS段:编译时分配,未初始化的全局变量和静态变量

    数据区:编译时分配,已经初始化的全局变量和静态变量

    代码段:编译时分配

    3)动态分配内存函数:

    1))viod * malloc(unsigned size);

    #include <stdlib.h>

    从内存的堆区分配大小为size个字节的联系的内存空间,如果内存分配成功,返回内存的首地址,失败,返回NULL。所以需要判断是否分配成功

    2))calloc分配

    calloc(块数,长度);

    3))realloc函数可以给已经存在的空间扩充大小,返回新的地址

    //
    //  main.c
    //  分配内存
    //
    //  Created by fanyafang on 15/11/5.
    //  Copyright © 2015年 itcast. All rights reserved.
    //
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, const char * argv[]) {
        //分配空间
        //int *p=(int *)malloc(4*sizeof(int));
        //使用一个函数给malloc申请的空间进行初始化
        //memset(p,'a',16);
        
        int *p=(int *)calloc(4, 4);//可以自动初始化
        
        p=realloc(p, 40*sizeof(int));
        if(p==NULL){
            printf("申请失败!");
        }else{
            printf("申请成功!");
            printf("%d
    ",*p);
            *p=10;
            *(p+1)=100;
            *(p+2)=30;
            *(p+3)=120;
            *(p+39)=10000;
            printf("%d
    ",*(p+39));
        }
        
        
        return 0;
    }

    4.野指针和内存泄露

    int *p=(int *)calloc(4, 4);//p存储在栈区,p指向的内容在堆区

    在p被释放之前先要释放堆区中的内容,否则会造成内存泄露,释放之后要赋值为NULL,不然还是可以访问

    //应该使用free函数释放内存空间
        free(p);//释放后p是一个野指针
        //p=NULL;
        *p=1000;

    5.指针函数:返回值是指针类型的函数

    //
    //  main.c
    //  指针函数
    //
    //  Created by fanyafang on 15/11/5.
    //  Copyright © 2015年 itcast. All rights reserved.
    //
    
    #include <stdio.h>
    
    char * printDay(int n){
        char * days[]={
            "星期一",
            "星期二",
            "星期三",
            "星期四",
            "星期五",
            "星期六",
            "星期日"
        };
        return n>0&&n<8?days[n-1]:"输入错误";
    }
    
    int main(int argc, const char * argv[]) {
        int n=0;
        printf("请输入一个数字:
    ");
        scanf("%d",&n);
        printf("%s
    ",printDay(n));
        
        return 0;
    }

     6.函数指针

    在C语言中,一个函数总是占用一段连续的内存空间,而函数名就是该函数所占内存空间区的首地址

    定义函数指针:int (*p)(int a , int b );或者:int (*p)(int  , int  );

    函数指针的使用:

    调用函数,同函数名的使用,可以任意调用函数

     

     

     

  • 相关阅读:
    django channle的使用
    显示react配置
    细思极恐-你真的会写java吗?
    Java String 面试题以及答案
    2017年--10年java大神告诉你开发最常用的百分之二十的技术有哪些?
    2017常见的50道java基础面试题整理(附答案)
    java如何填写简历?(干货篇)
    你所不知道的 Java 之 HashCode
    Java一般要学多久?
    Java 线程的中断机制
  • 原文地址:https://www.cnblogs.com/fanglove/p/4939092.html
Copyright © 2011-2022 走看看