《C Primer Plus》读书笔记——存储类、链接和内存管理

简介: 背景距离上次写读书笔记的日子已有半个月了。这段时间一直在做摄像头直立平衡车,也把《C Primer Plus》的中级部分扫了一遍。现在做赛道算法识别遇到瓶颈了,就想把读书笔记补回来。

背景

距离上次写读书笔记的日子已有半个月了。这段时间一直在做摄像头直立平衡车,也把《C Primer Plus》的中级部分扫了一遍。现在做赛道算法识别遇到瓶颈了,就想把读书笔记补回来。原计划是写指针和数组2的。现在发现还不如直接开新篇,反正之前没写的变长数组之类的也会提及。所以就有这篇存储类、链接和内存管理。虽说这里部分的知识都有在平时码代码时用到,认识得深一点,但是还是有很多过目就忘的,遂烂笔头记之。

存储类

C为变量提供了5种不同的存储模型,或称存储类。还有基于指针的第6种存储模型。可按照一个变量的存储时期(storage duration)、作用域(scope)及链接(linkage)来描述它。

作用域

作用域描述了程序中可以访问一个标识符的一个或多个区域。可以是代码块作用域、函数原型作用域或者文件作用域。

  • 代码块:整个函数体或一个函数内任一复合语句。
    C99允许在一个代码块任意位置声明变量:
    for(int i = 0; i<10; i++) //合法

  • 函数原型:从变量定义处一直到原型声明的末尾。
    如变长数组:
    void use_a_VLA(int n, int m, ar[n][m]);

  • 文件:在所有函数之外定义的变量,即全局变量。

链接

一个C变量具有下列链接之一:外部链接(external linkage),内部链接(internal linkage)或空链接(no linkage)。

  • 具有代码块作用域或函数原型作用域的变量有空链接,意味着他们是由其定义所在代码块或函数原型所私有的。
  • 具有外部链接:可在多文件使用。
  • 具有内部链接:可在单文件使用。

存储时期

一个C变量有以下两种存储时期之一:静态存储时期(static storage duration)和自动存储时期(automatic storage duration)。

  • 具有文件作用域的变量具有静态存储时期,它在程序执行期间将一直存在。
    注意:对于具有文件作用域的变量,关键词static表明链接类型,并非存储时期。一个使用static声明了的文件作用域变量具有内部链接,而所有的文件作用域变量,无论它具有内部还是外部链接,都具有静态存储时期。
  • 具有代码块作用域的变量一般情况下具有自动存储时期。
  • 程序进入该代码块,将为这些变量分配内存,退出代码块时,将释放内存。

5种存储类

存储类和函数

函数也有存储类,可以时外部的、静态的或内联的。
若无static,默认是extern。

随机数函数与静态变量

/* 自写随机数函数,包含两文件 */

/* s_and_r.c */
static unsigned long int next = 1; //种子

int rand(void)
{
    /*产生伪随机数的公式*/
    next = next * 1103515245 + 12345;
    return (unsigned int)(next / 65536) % 32768;
}

void srand(unsigned int seed)
{
    next = seed;
}


/* r_drive.c */
#include <stdio.h>
extern void srand(unsigned int x);
extern int rand(void);

int main(void)
{
    int count;
    unsigned seed;
    printf("Please enter your choice for seed.\n");
    while(scanf("%u", &seed) == 1)
    {
        srand(seed); //重置种子
        for(count = 0; count < 5; count++)
        printf("%hd\n", rand() );
        printf("Please enter next seed (q to quit):\n"); 
        //实际上输入的不是无符号十进制数应该就可以退出
    }
    printf("Done.\n");
    return 0;
}

另外还有利用计算机掷出非现实的任意个任意面骰子的程序。

分配内存:malloc()和free()

函数malloc() 接受一个参数:所需内存字节数。然后malloc()找到可用内存中一个大小适合的块。内存是匿名的,即malloc()分配了内存,但没有为它指定名字。然而,它可以返回那块内存第一个字节的地址。因此,可以把那个地址赋值给一个指针变量,并使用该指针来访问那块内存。malloc()可指向char或void(通用指针)的指针,可返回数组指针、结构指针等等。若找不到所需的空间,它将返回空指针。

double * ptd; //声明指针来存放块在内存中的位置
ptd = (double *)malloc(30 * sizeof(double)); //使用malloc请求一个存储块,类型指派(double *)在C中可选,在C++必须。

这段代码请求30个double类型值的空间,并把ptd指向该空间所在位置。注意ptd是作为指向一个double类型值的指针声明的。数组的名字是它第一个元素的地址。可用ptd[n]来访问第n个元素。

现在,创建一个数组有三种方法:

  • 声明一个数组,声明时用常量表达式指定数组维数,然后可用数组名访问数组元素。
  • 声明一个变长数组,声明时用变量表达式指定数组维数,然后用数组名来访问数组元素。
  • 声明一个指针,调用malloc(),然后使用该指针来访问数组元素。

一般地,对应每个malloc(),应调用一次free()。free的参数是先前malloc返回的地址,它释放先前分配的内存。在函数末尾处调用free()可防止内存泄漏(memory leak)。

存储类与动态内存分配

理想的程序将其可用内存分为三个独立的部分:一个是具有外部、内部及空链接的静态变量的;一个是自动变量的,另一个是动态内存分配的。
- 声明不同存储类,变量使用内存时间不同,将这一部分内存处理为一个堆栈。这样的新变量在内存中创建时按顺序加入,消亡时按相反顺序移除。
- 动态分配的内存在调用malloc等时产生,调用free时释放。这样的内存可能是碎片状的。

目录
相关文章
|
12月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
964 55
|
10月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
3058 0
|
10月前
|
存储 缓存 NoSQL
内存管理基础:数据结构的存储方式
数据结构在内存中的存储方式主要包括连续存储、链式存储、索引存储和散列存储。连续存储如数组,数据元素按顺序连续存放,访问速度快但扩展性差;链式存储如链表,通过指针连接分散的节点,便于插入删除但访问效率低;索引存储通过索引表提高查找效率,常用于数据库系统;散列存储如哈希表,通过哈希函数实现快速存取,但需处理冲突。不同场景下应根据访问模式、数据规模和操作频率选择合适的存储结构,甚至结合多种方式以达到最优性能。掌握这些存储机制是构建高效程序和理解高级数据结构的基础。
1002 1
|
10月前
|
存储 弹性计算 固态存储
阿里云服务器配置费用整理,支持一万人CPU内存、公网带宽和存储IO性能全解析
要支撑1万人在线流量,需选择阿里云企业级ECS服务器,如通用型g系列、高主频型hf系列或通用算力型u1实例,配置如16核64G及以上,搭配高带宽与SSD/ESSD云盘,费用约数千元每月。
1248 0
|
存储 算法 Java
JVM: 内存、类与垃圾
分代收集算法将内存分为新生代和老年代,分别使用不同的垃圾回收算法。新生代对象使用复制算法,老年代对象使用标记-清除或标记-整理算法。
228 6
非静态内部类持有外部类引用导致内存溢出
非静态内部类持有外部类引用导致内存溢出
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
788 4
|
存储 Java 程序员
结构体和类的内存管理方式在不同编程语言中的表现有何异同?
不同编程语言中结构体和类的内存管理方式既有相似之处,又有各自的特点。了解这些异同点有助于开发者在不同的编程语言中更有效地使用结构体和类来进行编程,合理地管理内存,提高程序的性能和可靠性。
337 3
|
存储 缓存 Java
结构体和类在内存管理方面的差异对程序性能有何影响?
【10月更文挑战第30天】结构体和类在内存管理方面的差异对程序性能有着重要的影响。在实际编程中,需要根据具体的应用场景和性能要求,合理地选择使用结构体或类,以优化程序的性能和内存使用效率。