malloc和free以及C程序中的类型限定符和静态存储、自动存储、动态存储

    技术2022-07-11  95

    1. time函数

    ○ time函数---time_t time(time_t * timer),参数是一个time_t类型的指针,用于存储返回的时间值,这个参数可以为空 ○ 获取当前的系统时间,返回的结果是一个time_t类型,其实就是一个大整数。

    2. 动态内存分配malloc()、calloc()和free()

    ○ 动态内存分配 ○ 通俗一点就是向计算机要内存空间,是在程序运行时,再向计算机要内存 ○ 一般是用malloc函数 § #include<stdlib.h> § void* malloc(size_t size); § 利用malloc申请到的内存空间是以字节为单位的,返回的结果是void *,一般需要类型转换为自己需要的类型 int *a; a=(int*)malloc(n*sizeof(int)); //本语句的意思就是通过malloc函数向计算机申请一块内存空间,这个空间 的大小是n*sizeof(int),返回的是一个void*类型的指针,也就是一个指向未知类型数据的地址,之后再把这个指针 转化为我们需要的类型---int * § 如果申请失败了就会选择返回0或者是NULL,失败时可以通过exit()函数结束程序 ® void exit(int status) ◊ 功能:关闭所有文件,终止正在执行的进程 ◊ exit(1)--- 异常退出 ◊ exit(x)--- x不为0就表示异常退出 ◊ exit(0)--- 表示正常退出 ◊ exit函数将参数传给了操作系统,以供其他程序调用 ® exit和return的区别 1. return返回函数值,是关键字; exit 是一个函数。 2. return是语言级别的,它表示了调用堆栈的返回;而exit是系统调用级别的,它表示了一个进程的结束。 3. return是函数的退出(返回);exit是进程的退出。 4. return是C语言提供的,exit是操作系统提供的(或者函数库中给出的) 5. return用于结束一个函数的执行,将函数的执行信息传出给其他调用函数使用;exit函数是退出应用程序, 删除进程使用的内存空间,并将应用程序的一个状态返回给OS(操作系统),这个状态标识了应用程序的一些 运行信息,这个信息和机器和操作系统有关,一般是0为正常退出,非0为非正常退出。 6. 非主函数中调用return和exit效果很明显,但是在main函数中调用return和exit的现象就很模糊,多数情 况下现象都是一致的。 ○ 利用动态内存分配技术可以创建变长数组 § 也即声明一个指针,调用malloc(),将其返回值赋给指针,用指针访问数组元素 ○ 释放内存空间free() □ free(a); □ 不能对同一块内存释放两次 □ 只能还申请来的空间的首地址(注意:变量可以不一样,但是地址必须一样) □ 避免内存泄漏 calloc函数 ○ long * newmem; ○ newmem = (long *)calloc(100, sizeof (long)); ○ 函数声明如下: □ void *calloc(size_t nmemb, size_t size); ○ 相比malloc函数,calloc有两个参数,前一个是申请内存单元的数量,后一个是申请内存单元的大小 ○ 该函数将申请的所有内存都内置为0.

    3. 程序的可用内存可以广义上分为3类

    ○ 供静态变量使用的静态存储区 □ 编译时确定内存数量,程序执行时被创建,结束时释放 ○ 供自动存储类别变量使用的区域 □ 程序进入变量所在的块内部时,变量存在;离开时,变量消失 □ 这部分内存称为栈内存 ○ 供动态内存分配使用的区域 □ malloc()、calloc()等相关函数创建 □ free()释放 □ 可以在一个函数中申请、另一个函数中释放 ○ 动态内存一般要比栈内存慢

    4. C程序中的类型限定符:在一条声明中多次使用同一个限定符, 多余的限定符将被忽略

    a. const □ 声明普通变量和数组时,表明数据不可以修改,是常量 □ 在指针和函数形参中使用const § const在*前,表示指针指向的值是const---无法用指针去修改该值、 ® 若在函数形参中,用于保护数组不被修改 § const在*后,表示指针本身的值是const---指针不能指向别处 □ 对全局数据使用 § 使用全局数据是冒险行为 § 数据有可能被修改,所以使用const限定,可以保证数据不变,避免这种风险 § 文件之间共享从const数据 ® 方法1:一个文件中定义式声明、其他文件中引用式声明(extern) ® 方法2:将需要共享的数据定义在头文件中、然后所有要使用该数据的文件都包含这个头文件 ◊ 这种方法在头文件中定义必须使用static限定符,用于保证这个数据在每一个文件中都是私有的; 否则,待编译之后头文件展开---那么每个文件中都有一个对数据的定义式声明,这是违法的 b. volatile □ 告知计算机该数据是一个可变数据,代理(我理解为其他的非程序本身的可以改变程序中变量数据的机制)可 以改变该数据的值 □ 该限定针对的是代理而不是程序 □ 如果有这个限定词,那么编译器在优化时,见到这个词之后就表示不优化 □ 如果没有这个限定词,那么C标准会尝试优化 □ 可以和const 同时限定某变量,两者并不冲突---const表示程序不能修改,volatile表示代理可以修改 c. restrict(限定的指针必须是访问数据对象唯一且初始的方式) □ 也是用于编译器优化,来告诉编译器是否可以优化代码 □ 对于restrict限定的变量,如果在程序中出现可以进行合并等优化条件的语句,编译器就会认为涉及该变量的语句 之间,不存在被其他标识符修改的情况,所以可以安全的进行优化(因为该变量名是访问该变量唯一的方式,所以 其他标识符必定无法访问) □ 如果没有restrict限定,那么为了保险起见,编译器会认为,涉及该变量的语句之间,存在其他标识符修改数据的 情况,所以不可以进行优化语句。 d. _Atomic □ 主要应用于并发程序设计(多线程) □ 要通过各种宏函数来访问原子类型。 当一个线程对一个原子类型的对象执行原子操作时, 其他线程不能访问该对象。
    Processed: 0.011, SQL: 9