一、存储类别:
C语言中 对象 指的是 一块内存,可以存储一个或者多个值;
C++语言中 对象 指 类对象,其定义包括数据和允许对数据进行的操作;
存储期 描述标识符所访问的对象的生存期;作用域和链接描述了标识符的可见性;标识符用于访问对象;
1、作用域:描述可访问标识符的区域
块作用域--{ }括起来的区域,包括函数形参,C99允许在块中任意位置声明变量;
函数作用域--仅用于goto语句的标签,无条件转移语句;
函数原型作用域--用于函数原型中的形参名,范围从形参定义处到原型声明结束;
文件作用域--变量定义在函数之外,范围从定义处到该定义所在的文件末尾均可见;文件作用域的变量又称全局变量;一个具有文件作用域的变量的实际可见范围是整个翻译单元,每个翻译单元均对应一个.c源代码文件和他所包含的所有.h头文件;
2、链接:C语言变量有3种链接属性
无链接变量--具有块作用域、函数作用域、函数原型作用域的变量仅属于定义他们的块、函数、原型私有;具有文件作用域的变量可以是外部链接或内部链接;
外部链接(默认)文件作用域--描述可以延伸指其他翻译单元的作用域(全局作用域/程序作用域),可以在多文件程序中使用;
内部链接文件作用域--只能在一个翻译单元中使用;简称(文件作用域);对文件作用域变量,关键字static表明其具有内部链接属性;
3、存储期:静态存储期、线程存储期、自动存储期、动态分配存储期
具有静态存储期的变量,在程序的执行期间一直存在。如文件作用域变量;块作用域变量在声明前加上关键字static也就具有了静态存储期;
具有线程存储期的变量,从被声明到线程结束一直存在。并发程序设计中,程序执行可分为多个线程。关键字_Thread_local声明的对象,每个线程都获得该变量的私有备份;
具有自动存储期的变量是块作用域变量,进入块分配退出块时释放内存;
4、自动变量
属于自动存储类别的变量具有自动存储期、块作用域、无链接。可以用关键字auto进行指定;
5、寄存器变量
寄存器变量存储在CPU的寄存器中即存储在最快的可用内存中,用register存储类别说明符声明寄存器变量;
6、块作用域的静态变量
用static声明,与块作用域的自动变量一样有相同的作用域,但程序离开他们所在的函数时,这些变量不会消失,计算机中多次函数调用之间会记录他们的值;
7、外部链接的静态变量
该类型变量具有文件作用域、外部链接、静态存储期,若一个源代码文件使用的外部变量定义在另一个源代码文件中,则必须用关键字extern在该文件中声明该变量;
8、内部链接的静态变量
该类型变量具有文件作用域、内部链接、静态存储期,用static定义,仅能用于一个翻译单元;
9、多文件
当复杂的C程序由多个.c源代码文件组成即具有多个翻译单元。这些.c文件若想共享一个外部变量,需要在一个文件中进行定义式声明并初始化(只有在这能初始化),在其它文件均需要使用extern关键字进行引用式声明实现共享;UNIX系统允许不使用extern,默认第一个初始化声明为该变量定义。
10、6种存储类别说明符
11、存储类别与函数
函数存储类别分为 外部函数与静态函数,默认为外部函数,静态函数加static(static说明该函数属于特定模块私有)用extern声明定义在其他文件中的函数;
12、存储类别选择
默认自动存储类别,“按需知道”,尽量在函数内部解决该函数的任务,值共享那些需要共享的变量;
注意:
static指的是静态变量,与全局变量的存储方式不同,该变量分配在静态变量区,不会随着函数调用的结束而被清除。如果该函数再次被调用的话,那么它的值是上一次调用结束后的值。
C语言中,auto用于指定为自动变量,由编译器自动分配和释放,通常在栈上分配。
C++中,auto为类型指示符,auto定义的变量,可以根据初始化的值,在编译时推导出变量名的类型。
作为循环或者if语句的一部分即使不用花括号也是一个块;整个循环时它所在是块的子块,循环体的整个循环块的子块。
变量通常存储在计算机内存中,寄存器变量存储在CPU的寄存器中;
寄存器 :寄存器是有触发器或锁存器组成,通常由触发器组成,寄存器拥有非常高的读写速度,所以在寄存器之间传递数据非常快
内存 :内存就是存储器,由半导体器件构成。
计算机的存储层次(memory hierarchy)之中,寄存器(register)最快,内存其次,最慢的是硬盘。
不能在函数的形参中使用static;
如果未初始化外部变量,他们会被自动初始化为0;
extern用于指定变量为外部变量,即在另外的目标文件中定义,可以认定该变量是由另外文件所声明的。不能用关键字extern创建外部定义,只用它来引用现有的外部定义;
定义声明在函数之外的变量默认 文件作用域、外部链接、静态存储期;
const关键字声明定义的变量,在初始化后值不会改变;
使用extern关键字进行引用式声明表明该函数定义在其他文件中,那么在引用的这个文件中只需要函数声明、函数调用,不需要进行函数定义;
二、随机数函数与静态变量
伪随机生成器rand()、重置种子器srand(),头文件均为<stdlib.h>
rand()函数原型:int rand(void);
srand()函数原型:void srand (usigned int seed);
若要生成[n,m]范围内随机整数:int num =rand()%(m-n+1)+n; n<= num <=m;
自动重置种子:#include<time.h>
srand( (unsigned int) time (0) );
time()函数,头文件<time.h>;该函数返回从1970年1月1日0时0 分0秒起到现在的秒数,该函数返回值数据类型为time_t类型(与具体系统有关,故一般强制类型转换),若括号内传递的参数为0,则通过返回值机制来提供值;
localtime()函数,将时间数值变换成本地时间,考虑到本地时区和夏令时标志;
三、掷骰子
四、分配内存:malloc()、calloc()和free()
malloc()和free()函数原型定义在<stdlib.h>中,二者配套使用;
malloc()函数,参数为所需内存字节数,该函数找到匿名的空闲内存块,返回值为内存块首地址/指针;
calloc()函数,2个参数,第一个是所需存储单元数量,第二个是存储单元大小;该函数把块中所有位都设置为0;
free()函数的参数是之前malloc()返回的地址,该函数释放之前malloc()或者calloc()分配到的内存;
变长数组也可以分布动态内存,但他是自动存储类型,不必使用free(0,程序在离开变长数组所定义的块是,器占用的内存空间就会被自动释放;
程序把它可用的内存分为3部分:供静态变量、供自动变量、供动态内存分配;
静态存储类别程序开始执行时被创建,程序结束时被销毁;
自动存储类别程序进入变量定义所在块时存在,在程序离开块时消失;栈(可看作可重复利用的工作区);
动态分配的内存由程序员管理,在调用malloc()一类函数时存在,在调用free(0时释放;
五、ANSI C语言类型限定符
1、const:初始化后不能改变它的值;在指针中应用位于*左侧限定指针指向的数据不能改变,位于*右侧限定指针本身不能改变;对全局数据使用const可以不免程序的任何部分都可以更改数据;在文件间共享const数据两种思路:一是在一个文件定义式声明,其他的使用extern引用式声明;二是把const变量放在一个头文件中(必须用关键字static声明);
2、volatile:告知计算机,代理(而不是变量所在的程序)可以改变该变量的值;若声明中没有该关键字,编译器会假定变量的值在使用过程中不变并尝试优化代码;
3、restrict:只能用于指针表明该指针是访问数据对象唯一且初始的方式,使用该关键字,编译器就可以选择捷径优化计算;
4、_Atomic
注意:
对一个数%n求模值,得到的值在0~n-1之间;