C的温故而知新:存储类别、链接和内存管理(C Primer Plus第十二章)
存储类别、链接和内存管理
这一章主要涉及到的是一些偏概念的东西,基本上偏向于自己去理解这部分内容。很好地理解这一章可以更好地控制程序,合理的利用内存存储数据。
C语言提供了多种不同的模型或存储类别在内存中存储数据。作用域有块作用域、函数作用域、函数原型作用域或文件作用域。链接有外部链接、内部链接和无链接。存储器有四种,静态存储期、线程存储期、自动存储期、动态分配存储期。
自动变量:一般创建变量,默认是自动变量,也可以显示使用关键字auto,块作用域,程序在进入该变量声明的块时变量存在,在退出该块时变量消失,原来占用的内存位置现在可以做为他用。
寄存器变量:存储类别说明符register,幸运的话,可以将变量放到CPU寄存器中,访问和处理的速度更快,无法获得寄存器变量的地址,倘若不幸运,没有放到寄存器中,就会变成普通的自动变量,但是仍不能获取到地址。可声明的类型有限。
快作用域的静态变量:在块中。以存储类别说明符static声明的变量,块作用域,但是出块之后,仍不会消失。不能在函数的形参中使用static。
外部链接的静态变量:把变量的定义时声明放到函数的外面。可以在函数中使用extern进行引用时声明。作用域是从声明处到文件结尾。可以在其他文件中引用这部分变量。
内部链接的静态变量:用存储类别说明符static定义的静态变量,大概和上面这一个类似,只是只能在同一个文件内使用。
函数也有存储类别,可以分为外部函数(默认),静态函数,内联函数(后续介绍)。外部函数可以被其他文件的函数访问,但是静态函数只能用于其定义的文件。
随意使用外部存储类别的变量导致的后果远远超过了它所带来的便利。唯一例外的是const数据,因为它们在初始化之后就不会改变,不用担心被意外修改。
还可以使用库函数分配和管理函数。malloc函数和free函数。
malloc函数:接受一个参数,所需的内存字节数,然后函数会找到合适的内存空间,这块内存是匿名的,返回动态分配内存块的首字节地址。如果分配内存失败,会返回空指针。如果内存分配失败,可以调用exit函数结束程序。
指向void的指针:相当于一个通用指针。把其赋值给任意类型的指针完全不用考虑类型匹配的问题。
free函数,接受的参数是之前malloc返回的地址,free函数释放malloc函数分配的地址。不能用free释放通过其他方式分配的内存。不能释放同一块内存两次
calloc函数:接受两个参数,第一个是所需的存储单元数量,第二个是存储单元的大小(以字节为单位),该函数会将块中的所有位都设置为0.同样可以用free函数去释放其分配的内存。
恒常性和易变性:分别用关键字const和volatile来声明,这两个类型是限定类型。他们现在是幂等的,可以在一条生命中多次使用同一个限定符,多余的限定符将被忽略。
声明指针时,const放在*号左侧任意位置,限定了指针指向的数据不能改变;const放在*号右侧,限定了指针本身不能改变。
volatile限定符:代理可以改变变量的值。可以用const和volatile限定一个值,设置为程序不能更改的变量,但是可以通过代理改变。
restrict类型限定符:允许编译器优化某部分代码以更好的支持运算。只能用于指针,表明该指针是访问数据对象的唯一且初识的方式。还可以在形参中使用,意味着编译器可以假定在函数体内其他标识符不会修改指针指向的数据。
_Atomic类型限定符:原子类型声明,多用于多线程开发。其他线程不能访问原子类型声明的变量。