返回
基础
分类

(1)第一个参数是命令行的字符串数,在代码块中定义的变量具有代码块作用域

日期: 2019-11-15 15:02 浏览次数 : 179

12.1 存储类

存储时期:变量在内存中保存的时间。变量的作用域和链接一起表明程序的哪些部分可以通过变量名来使用该变量。
不同的存储类提供了变量的作用域、链接以及存储时期的不同组合。

12.1.1 作用域

作用域描述了程序中可以访问一个标识符的一个或多个区域。一个C变量的作用域可以是代码块作用域、函数原型作用域,或者文件作用域。
在代码块中定义的变量具有代码块作用域,从该变量被定义的地方到包含该定义的代码块的末尾该变量均可见。另外,函数的形式参量尽管在函数的开始花括号前进行定义,同样也具有代码块作用域,隶属于包含函数体的代码块。
传统上,具有代码块作用域的变量都必须在代码块的开始处进行声明。C99放宽了这一限制,允许在一个代码块中任何位置声明变量。
函数原型作用域从变量定义处一直到原型声明的末尾。这意味着编译器在处理一个函数原型的参数时,它所关心的只是该参数的类型,而不关注参数名字。(除VLA外)
一个所有函数之外定义的变量具有文件作用域,它从定义处到包含该定义的文件尾都是可见的。

另外还有一种被称为函数作用域的作用域,但它只适用于goto语句使用的标签。

12.1.2 链接

一个C变量具有下列链接之一:外部链接、内部链接或空链接。
具有代码块作用域或者函数原型作用域的变量具有空链接,意味着它们是由其定义所在的代码块或函数原型所私有的。
具有文件作用域的变量可能有内部或者外部链接。
一个具有外部链接的变量可以在一个多文件程序的任何地方使用。
一个具有内部链接的变量可以在一个文件的任何地方使用。

12.1.3 存储时期

如果一个变量具有静态存储时期,它在程序执行期间将一直存在。具有文件作用域的变量具有静态存储时期。
所有的文件作用域变量,无论它具有内部链接,还是具有外部链接,都具有静态存储时期。

12.1.4 自动变量

默认情况下,在代码块作用域或函数的头部定义的任意变量都属于自动存储类。也可以通过显示的使用关键字auto使您的这个意图更清晰。
语句若为循环或者if语句的一部分,即使没有使用{},也认为是一个代码块。

12.1.5 寄存器变量

声明一个寄存器类变量仅是一个请求,而非一条直接的命令。所以可能达不成目的,而成为一个普通的自动变量。
可以使用register声明的类型是有限的。例如,处理器可能没有足够大的寄存器来容纳double类型。

12.1.6 具有代码块作用域的静态变量

静态变量和外部变量在程序调入内存时已经就位了。

12.1.7 具有外部链接的静态变量

把变量的定义声明放在所有函数之外,即创建了一个外部变量。为了程序更加清晰,可以使用extern关键字来再次声明它。如果变量是在别的文件中定义的,使用extern来声明改变量是必须的。
如果在函数的声明中漏掉了extern,就会建立一个独立的自动变量。
外部变量的作用域:从声明的位置开始到文件结尾为止。
和自动变量一样,外部变量可以被显示地初始化。不同于自动变量的是,如果您不对外部变量进行初始化,它们被自动赋值0。

main()
{
external int tern;
第一次声明tern称为定义声明,第二次声明称为引用声明。
不要用关键字extern来进行外部定义,只用它来引用一个已经存在的外部定义。
一个外部变量只可进行一次初始化,而且一定是在变量被定义时进行的。
extern char permis='u';   //错误

12.1.8 具有内部链接的静态变量

它只可以被与它在同一个文件中的函数使用。

1、main可以没有参数或者有两个参数:
(1)第一个参数是命令行的字符串数
(2)第二个参数是一个指向字符串的指针数组

12.2 存储类说明符

C语言中有5个作为存储类说明符的关键字,它们是auto、register、static、extern以及typedf。typedf与内存存储无关,由于语法原因被归入此类。不可以在一个声明者使用一个以上存储类说明符。
auto:一个变量具有自动存储时期,该说明符只能用在具有代码块作用域的变量声明中。
register:也只能用在具有代码块作用域的变量声明中,它的使用也使您不能获得变量的地址。
static:用于具有代码块作用域的变量声明时,使该变量具有静态存储时期,从而得以在程序运行期间存在并保留其值。用于文件作用域的变量声明时,表明该变量具有内部链接。
extern:表明您在声明一个已经在别处定义了的变量。

2、stdlib.h
(1)atoi(char * str);//将字符串转换成整数,失败返回0
(2)atol(char * str);//转换称long类型
(3)atof(char * str);//转换称double类型
(4)strtol(char * str, char **endptr, int (5)base);//把字符串转换成double类型,还可以识别并报告字符串中非数字的第一个字符,还可以指定数字基数
(6)strtoul(char * str, char **endptr, int (7)base);//把字符串转换成double类型,还可以识别并报告字符串中非数字的第一个字符,还可以指定数字基数
strtod(char * str, char **endptr);//把字符串转换成double类型,还可以识别并报告字符串中非数字的第一个字符
3、C变量的链接
(1)分为外部链接、内部链接、空链接
(2)居右代码块作用于或者函数原型作用域的变量有空连接,由其定义所在的代码块或函数原型所私有
(3)具有文件作用域的变量有外部链接,一个外部链接的变量可以在一个多文件程序的任何地方使用
必赢手机登录网址 ,(4)具有文件作用域的变量有内部链接,一个内部链接的变量可以在一个文件的任何地方使用
4、自动变量
(1)属于自动存储类的变量居右自动存储时期、代码块作用域和空链接。默认下,在代码块或函数的头部定义的任意变量都属于自动存储类,也可以显式使用auto定义:auto int plox;//auto称为存储类说明符
(2)在嵌套代码块中,如果在内层代码块定义了一个具有和外层代码块变量同一名字的变量,内层代码块定义的名字是内层代码块所使用的变量,称为内层定义覆盖了外部定义
(3)除非显式初始化自动变量,否则它不会被自动初始化,未初始化的值是先前占用分配给它的空间的任意值
5、寄存器变量
(1)与自动变量一样,具有代码块作用于、空链接、以及自动存储时期,
(2)通过存储类说明符register定于:register int quick;
(3)不能对寄存器变量使用地址运算符&
(4)有可能寄存器变量不在寄存器中,而在高速内存中,但依然不能对它使用地址运算符

12.3 存储类和函数

函数也具有存储类,可以是外部的或者静态的。外部函数可以被其它文件中的函数调用,而静态函数只可以在定义它的文件中使用。

6、具有代码块作用域的静态变量
(1)代码块运行完,静态变量不消失
(2)使用const定义:const int stay;
(3)对函数参数不能使用static
7、具有外部链接的静态变量
(1)居右文件作用域、外部链接和静态存储时期
(2)把变量的定义声明放在所有函数之外,即创建了一个外部变量
(3)可使用extern关键字声明,若变量是在别的文件中定义的,使用extern来声明变量就是必须的
(4)外部变量在本地使用可不声明,如要声明需要添加extern关键字(对于数组,不要填写数组长度),如果没有添加则会覆盖外部变量而创建自动变量
(5)如果不显式地对外部变量进行初始化,外部变量会自动被赋值为0
8、具有内部链接的静态变量
(1)具有静态存储时期、文件作用于以及内部链接
(2)可被同一文件中的函数所使用,而普通的外部变量可以被程序的任意文件访问
(3)可用extern再次声明任何具有文件作用于的变量
9、多文件中的全局变量
(1)除了一个声明外,其他所有声明都必须使用关键字extern,并且只有在定义声明中才可以对该变量进行初始化
(2)除非在第二个文件中也声明了该变量(使用extern),否则在一个文件中定义的外部变量不可以用于第二个文件
(3)一个外部变量声明本只是使一个变量可能对其他文件可用
10、 存储类说明符
(1)auto, register, static, extern, typedef, 只能使用一个
(2)auto表明一个变量具有自动存储时期,该说明符只能用在具有代码块作用域的变量声明中
(3)register只能用于具有代码块作用域的变量,它将一个变量归入寄存器存储类,相当于请求将该变量存储在一个寄存器内,它的使用也使你不能获得变量的地址
(4)static在用于具有代码块作用域的变量的声明时,使该变量具有静态存储时期,从而得以在程序运行期间(即使在包含该变量的代码块并没有运行时)存在并保留其值。变量仍具有代码块作用域和空链接,static用于具有文件作用域的变量的声明时,表明该变量具有内部链接
(5)extern表明你在声明一个已经在别处定义了的变量。如果包含extern的声明具有文件作用域,所指向的变量必然具有外部链接。如果包含extern的声明具有代码块作用域,所指向的可能具有外部链接也可能具有内部链接,这取决于该变量的定义声明
11、存储类和函数
(1)double ganma();//默认是外部的函数
(2)static double beta();//beta函数被限定在该文件内,其他文件可使用相同名称的不同函数
(3)extern double delta();//使用关键字extern来声明在其他文件中定义的函数
12、随机数
(1)rand()产生随机数
(2)定义随机数的范围: rand() % sides + 1;
(3)rand()是伪随机数发生器,随机数的产生基于一个称为“种子”的数字
13、分配内存malloc, free, calloc
(1)double * ptd = (double *)malloc(30 * sizeof(double));
(2)可以用数组的方式来访问内存块的各个元素
(3)创建动态大小的内存空间(数组):double * ptd = (double *)malloc(n * sizeof(double));
(4)malloc创建的地址需要通过调用free释放内存:free(ptd);
(5)如果无法分配内存空间就返回空指针
(6)类型指派(double )在c可选,但在c++中是必须的
(7)stdlib.h 提供退出程序函数 exit(),其中常量参数:EXIT_SUCCESS, EXIT_FAILURE
(8)long
newmen = (long )calloc(100, sizeof(long));,块中的全部位置零,可用free释放内存
(9)malloc和变长数组的区别:变长数组是自动存储的,变长数组所用内存空间在运行完定义部分之后会自动释放
(10)malloc创建多维数组:int (
p2)[m] = (int ()[m])malloc(n m * sizeof(int));
14、类型限定词
(1)幂等性:const const const int n = 6;//相当于 const int n = 6;
(2)用const修饰指针,const float * pf;//pf指向一个常量浮点数值,指针指向的地址可改,指向的数据不可改
(3)float * const pt;//pt是一个常量指针,指向的地址不可改,指向的数据可改
(4)const float * const ptr;//ptr是一个指向常量的常量指针
(5)cosnt修饰函数参数const int array[], cosnt int * array, 表明array指向的数据是不可变的
(6)对全局变量使用const, 其他文件调用声明 extern const double PI, extern const char * MONTH[]
(7)类型限定词volatile表明该变量除了可被程序意外还可被其他代理改变
(8)类型限定词restrict允许编译器优化几种代码增强计算支持,只可用于指针,并表明指针是访问一个数据对象的唯一且初始的方式:int * restrict restar = (int *)malloc(10 * sizeof(int));
(9)void ofmout(int * const a1, int * restrict a2, int n);//以前的风格
void ofmouth(int a1[const], int a2[restrict], int n);//C99允许
double stic(double ar[static 20]);
15、标准I/O
(1)FILE *fp;
(2)fp = fopen(filename, "r");//打开文件失败返回NULL
(3)(ch = getc(fp)) != EOF //读取一个字符
(4)putc(ch, stdout); //相当于putchar(ch);
(5)fclose(fp);
(6)fopen()函数的模式字符串
①"r":打开一个文本文件,可以读取文件
②"w":打开一个文本文件,可以写入文件,先将文件的长度截为零,如果该文件不存在则先创建之
③"a":打开一个文本文件,可以写入文件,向已有文件的尾部追加内容,如果该文件不存在则先创建之
④"r+":打开一个文本文件,可以进行更新,也即可以读取和写入文件
⑤"w+":打开一个文本文件,可以进行更新(读取和写入),如果该文件存在则首先将其长度截为零,如果不存在则先创建之
⑥"a+":打开一个文本文件,可以进行更新(读取和写入),向已有文件的尾部追加内容,如果该文件不存在则先创建之,可以读取整个文件,但写入时只能追加内容
⑦"rb","wb","ab","ab+","a+b","wb+","w+b","ab+","a+b":与前面的模式相似,只是使用二进制而非文本模式打开文件
(7)putc(ch, fpout);//将ch字符写入到FILE指针fpout指定的文件中
(8)fp = getc(fp);//当尝试读入字符时发现已经达到文件结尾,getc()函数会返回一个特殊只EOF
(9)fclose(fp)函数关闭由指针fp指定的文件,同时根据需要刷新缓冲区,更正规的程序还要检查是否成功关闭了文件,如果文件成功关闭,fclose()函数将返回值0,否则返回EOF
(10)标准文件指针:标准输入stdin, 标准输出stdout, 标准错误stderr

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

malloc():它接受一个参数:所需内存字节数,然后malloc()找到可用内存中一个大小合适的块,返回那块内存第一个字节的地址,如果找不到所需空间,返回空指针。
double * ptd;
ptd=(double *)malloc(30 *sizeof(double));
这段代码请求30个double类型值的空间,并且把ptd指向该空间锁在位置。
现在创建数组有三种方法
1、声明一个数组,用常量表达式指定数组维数。
2、声明一个变长数组,声明时用变量表达式指定数组维数。
3、声明一个指针,调用malloc()。
一般地,对应每个malloc()调用,应该调用一次free()。函数free()的参数是先前malloc()返回的地址,不能使用free()来释放通过其它方式分配的内存。
在头文件stdlib.h有malloc()和free()的原型。
标准库提供了两个保证能够在所有操作系统下工作的返回值:EXIT_FAILURE指示程序异常终止,EXIT_SUCCESS指示程序正常终止。

12.4.1 free()的重要性

在编译程序时,静态变量的数量是固定的,在程序运行时也不改变。自动变量使用的内存数量在程序执行时自动增加或减少,但被分配的内存所使用内存数量只会增加,除非您记得使用free()。否则可能造成内存泄露。

12.4.2 函数calloc()

例子如下:
long * newmem;
newmem=(long *)calloc(100,sizeof(long));
函数calloc()还有一个特性:它将块中的全部位都置为0。
函数free()也可以用来释放由calloc()分配的内存。

12.4.3 动态内存分配与变长数组

VLA与malloc()都可以用来创建一个大小在运行时决定的数组。
区别在于VLA是自动存储的,即VLA所用内存空间在运行完定义部分之后会自动释放。
使用由malloc()创建的数组不必局限在一个函数中。

自动变量:将这一部分内存处理为一个堆栈,这意味着在内存中,新变量在创建时按顺序加入,在消亡时按相反顺序移除。

12.5 ANSI C的类型限定词

C99授予类型限定词一个新属性:它们现在是幂等的。这意味着可以在一个声明中不止一次地使用同一限定词,多余的将被忽略掉。
const const const int n=6;相当于const int n=6;
如果变量声明中带有关键字const,则不能通过赋值、增量或减量运算符来修改值。

12.5.1 类型限定词volatile

限定词volatile告诉编译器该变量除了可被程序改变以外还可被其他代理改变。典型的,它被用于硬件地址和与其它并行运行的程序共享的数据。
一个值可以同时是const和volatile。程序不能改变它的值,这一点使它成为const,但它被程序以外的代理改变,这使它成为volatile。

12.5.1 类型限定词restrict

关键字restrict只可用于指针,并表明指针是访问一个数据对象的惟一且初始的方式。
int ar[10];
int *restrict restar=(int *)malloc(10 *sizeof(int));
int *par=ar;
指针restar是访问由malloc()分配的内存的惟一且初始的方式,因此它可以使用这个关键字。
par指针既不是初始的,也不是访问数组ar中数据的惟一方式,因此不可以使用。
void * memcpy(void * restrict s1,void * restrict s2,size_t n);
把s1,s2声明为restrict意味着每个指针都是相应数据的惟一访问方式,因此它们不能访问同一数据块,即不能重叠。

存储类 存储时期:变量在内存中保存的时间。变量的作用域和链接一起表明程序的哪些部分可以通过变量名来使用该变量。 不同的存储...