第4章 函数与程序结构
Ø 如果函数定义中省略了返回值类型,则默认为int类型。
Ø 如果某个函数从一个地方返回时有返回值,而从另一个地方返回时没有返回值,该函数并不非法,但可能是一种出问题的征兆。在任何情况下,如果函数没有成功地返回一个值,则它的“值”肯定是无用的。
Ø 如果没有函数原型,则函数将在第一次出现的表达式中被隐式声明,例如:
sum += atof(line)
Ø 如果先前没有声明过的一个名字出现在某个表达式中,并且其后紧跟一个左圆括号,那么上下文就会认为该名字是一个函数名字,该函数的返回值将被假定为int类型,但上下文并不对其参数作任何假设。
Ø 好的函数声明风格:如果函数带有参数则要声明它们;如果没有参数,则使用void进行声明。如:int pop(void);
Ø 名字的作用域是指程序中可以使用改名字的部分。对于函数开头声明的自动变量来说,其作用域是声明该变量名的函数。实际上函数的参数可以被看成局部变量。
外部变量或函数的作用域是从它声明的地方开始,到其所在的文件的末尾结束。
如果要在外部变量的定义之前使用该变量,或者外部变量的定义与变量的使用不在同一个原文件中,则必须在相应的变量声明中强制性地使用关键字extern
Ø 将外部变量的声明和定义严格区分开来很重要。变量声明用于说明变量的属性(主要是变量的类型),而变量定义除此以外还将引起存储器的分配。
如果将以下语句放在所有函数的外部:
int sp;
double val[3];
那么这两条语句将定义外部变量sp与val,并为之分配存储单元,同时这两天语句还可以作为该原文件其余部分的声明。
而下面的两行语句:
extern int sp;
extern double val[];
为源文件的其余部分声明了一个int类型的外部变量sp以及一个doubel数组类型的外部变量val(该数组的长度在其他地方确定),但这两个声明并没有建立变量或为它们分配存储单元。
在一个源程序的所有源文件中,一个外部变量只能在某个文件中定义一次,而在其他文件中可以通过extern声明来访问它。
Ø 静态变量:用static声明限定外部变量与函数,可以其后声明的对象的作用域限定为被编译原文件的剩余部分。
通过static限定外部对象,可以达到隐藏外部对象的目的。意思是说使用static修饰的外部变量对其他文件不可见。
使用static声明函数,它使得这个函数只对本文件可见。
使用static声明内部变量。则此内部变量一直存在,不会随着所在函数的调用和退出而存在和消失。
Ø 存储器变量:register声明告诉编译器,它所声明的变量在程序中使用频率较高。其思想是,将register变量放在机器的寄存器中,这样可以使程序更小、执行速度更快。但编译器可以忽略此选项。
register声明形式如下:
register int x;
register char c;
register声明只适用于自动变量及函数的形式参数。
无论寄存器变量实际上是不是放在寄存器中,它的地址都是不能访问的。
Ø 初始化:在不进行显式初始化的情况下,外部变量和静态变量被初始化为0,而自动变量和寄存器变量则没有定义(即初值为无用的信息)。对于外部变量和静态变量来说,初始化表达式必须是常量表达式,且只初始化一次。
Ø C预处理器。
宏替换:宏定义形式如下:
#define 名字 替换文本
#define指令中的名字与变量名的命名方式相同,替换文本可以是任意字符串。通常,#define指令占一行,替换文本是#define指令行尾部的所有剩余内容,但也可以把一个较长的宏定义分成若干行,这是需要在待续的行末尾加上一个反斜杠符“/”。#define定义的名字的作用域从其定义开始,到被编译的源文件的末尾处结束。