1.环境
1.1 理论
在ANSI C的任何一种实现中,存在两种不同的环境:翻译环境和执行环境。在翻译环境(translation environment)中,源代码被转换为可执行的机器指令;执行环境(execution environment)用于实际执行代码。这两种环境不必位于同一台机器上,如:交叉编译器(cross compiler)。
翻译过程=编译过程+链接过程。源程序经编译后产生若干个目标文件;多个目标文件经链接后产生一个单一而完整的可执行程序。
编译过程=预处理+解析。
预处理就是对源代码进行一些文本操作,如去掉代码中的空格、用实际值代替由#define指令定义的符号、读入由#include指令包含的文件的内容。
解析阶段是产生绝大多数错误和警告信息的阶段。
目标代码是机器指令的初步形式,用于实现程序的语句。
优化过程(略)。
程序的执行:在绝大多数机器里,程序将使用一个运行时堆栈,它用于存储函数的局部变量和返回地址。程序同时也可以使用静态内存,存储于静态内存中的变量在程序的整个执行过程中将一直保留它们的值。
1.2实践
在绝大多数unix系统中,C编译器被称为 cc ,它可以用多种不同的方法来调用。
(1) 编译并链接一个完全包含于一个源文件的C程序: cc hello.c
(2) 编译并链接几个C源文件:cc main.c sum.c
(3) 编译一个C源文件,并产生一个目标文件(sum.o),以后再进行链接:cc -c sum.c
(4) 编译一个C源文件,并把它和现存的目标文件链接在一起:cc main.c sum.o
(5) 编译几个C源文件,并为每个文件产生一个目标文件:cc -c main.c sum.c
(6) 链接几个目标文件:cc main.o sum.o
为什么生成的可执行程序都是 a.out ?
具体原因我也不知道,但是使用命令:cc -o name hello.c ,就可以生成一个名称为 name 的可执行文件。 -o name 就是输出将输出的可执行文件命名为name的意思。
2. 词法规则
一个ANSI C 程序由声明和函数组成。函数定义了需要执行的工作,而声明则描述了函数或函数将要操作的数据类型。
三字母词:就是三个字符的序列,合起来表示另一个字符。三字母词使C环境可以在某些缺少一些必需字符的字符集上实现。下面是常见的9个三字母词:
(1) ??( 代表 [
(2) ??) 代表 ]
(3) ??< 代表 {
(4) ??> 代表 }
(5) ??- 代表 ~
(6) ??= 代表 #
(7) ??! 代表 |
(8) ??' 代表 ^
(9) ??/ 代表 \
思考:printf("Delete file (are you sure??):"); 的输出结果。
转义字符:所有的ASCII字符都可用 \ 加数字来表示。C语言中定义了一些字母前加 \ 来表示那些在特定情况下不能正常显示的ASCII字符,这样的字符就称为转义字符。
转义字符表:
\? 在书写练习多个问号时使用,防止它们被解释为三字母词。
\" 用于表示一个字符串常量内部的双引号。
\' 用于表示字符常量‘,例如 char a=' \' '; 错误形式为:char a=' ' ';
\\ 用于表示一个反斜杠,防止它被解释为一个转义字符。
注释:注释的形式为:/*注释体*/,注释不可以嵌套,当 /* 或 */ 出现在字符串字面值内部时,就不再起注释定界符的作用。源代码中所有能放空格的地方都可以放注释。
标识符(identifier):就是变量、函数、类型等的名字。标识符由大小写字母、数字和下划线组成,但不能以数字开头。C语言区分大小写。标识符的长度没有限制,但标准允许编译器忽略第31个字符以后的字符(就是说我们命名时可以不考虑长度限制,但是在第31个字符以后的字符起不起作用就要看编译器的了,若编译器区分前50个字符,那就前50个字符起作用,若编译器区分前60个字符,那就前60个字符起作用)。标准同时允许编译器对用于表示外部名字(也就是由连接器操纵的名字)的标识符进行限制,只识别前六位不区分大小写的字符。
下面是C语言中32个被保留的关键字,即程序员不能再以这些字符串作为标识符。
auto break case char const continue default do
double else enum extern float for goto if
int long register return short signed sizeof static
struct switch typedef union unsigned void volatile while
请格外注意以下这几个关键字:
auto const do enum extern goto register static struct typedef union volatile
一个C程序可能保存于一个或多个源文件中。虽然一个源文件可以包含超过一个的函数,但每个函数都必须完整地出现于同一个源文件中(虽然标准没有明确规定)。并且,合理组织方式应是一个C程序的源文件包含一组相关的函数。
程序的风格:
if 和 相关语句(while、switch等)的括号是这些语句的一部分,而不是它们所测试的表达式的一部分。函数原型也是如此。意思是:if( i<100) 这个语句中 if( ) 是一起的, i<100 是一起的。
在函数的定义中,返回类型出现于独立的一行中,而函数的名字则在下一行的起始处。见到这样的书写风格请不要奇怪。如:
int
sum( int a , int b )
{
return a+b;
}