1,简介
1.1重排字符
1.1.1空白和注释
空白:空行将程序的不同部分分割开来;制表符(tab)用于缩进语句,更好的显示程序的结构等。
注释:注释以符号/*开始,以*/结束结束。在C程序中,凡是空白的地方都可以插入注释,但是,注释不可以嵌套。在有些语言中,只是有时用于把一段代码“注释掉”,但并不将其真正从源文件中删除。在C语言中,如果一段代码内部原先就有注释存在,要从逻辑上删除一段代码,更好的办法是使用#if指令。例如:
#if 0
statements
#endif
在#if和#endif之间的程序就有效地从程序中去除,即使这段代码只见原先存在注释也无妨。
1.1.2预处理指令
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX_COLS 20
...
这几行称为预处理指令,他们是由预处理其器解释的,预处理器读入源代码,根据预处理指令进行修改,然后把修改过的源代码递交给编译器。
上面的第一个预处理指令预处理器用名叫stdio.h的库函数头文件的内容替换第一条#include指令语句,其结果就像是stdio.h的内容被逐字写到源文件的那个位置。第2、3条指令功能类似,只是替换的头文件不同。
提示:
可以在一个单独的文件中编写你所需的用于几个不同源文件的声明,然后用#include指令把这个文件包含到需要使用这些声明的源文件中。这样可避免拷贝时出现的错误。
预处理指令#define,他可以把名字MAX_COLS定义为20,由于他们被定义为字面值常量,所以这些名字不能出现在有些普通变量可以出现的的场合(如赋值符的左边),这些名字一般大写。如果觉得20列不够,可以简单的修改MAX_COLS的定义。
函数原型告诉编译器将在源文件中定义的函数的特征。
指针指定一个存储与计算机内存中的值的地址。
1.1.3 main函数
int main (void)
{
}
每个C程序都必须有一个main函数,因为它是程序的执行的起点,int表示函数返回一个整型值,关键字void表示函数不接受任何参数。
在C语言中,数组参数是以引用形式进行传递的,即传址调用,而标量和常量则是是按值传递的。
在C函数的参数传递规则表示如下:
所有传递给函数的参数值都是按值传递的,但是,当数组名作为参数时就会产生按引用传递的效果。
while循环,他先测试表达式的值,如果是假的(0)就跳过循环体,如果表达式的值是真的(非0),就执行循环体内的代码,然后再重新测试表达式的值。
C语言不存在“string”数据类型,但存在一个约定:字符串就是一串以NULL结尾的字符。NULL作为终止符,本身并不看作是字符串的一部分。字符串常量就是源程序中被双引号括起来的一串字符。
printf函数执行格式化输出。printf函数接受多个参数,其中第一个参数是一个字符串,描述输出的格式,剩余的参数就是需要打印的值。若数组input包含字符串Hi Girl!,那么下面这条语句
printf("Original input:%s\n", input);
的打印机结果是:
Original input: Hi Giirl!
后面以一个换行符终止。
常用printf格式代码
格式 | 含义 |
%d | 以十进制形式打印一个整型值 |
%o | 以八进制形式打印一个整型值 |
%x | 以十六进制形式打印一个整型值 |
%g | 打印一个浮点值 |
%d | 打印一个字符 |
%s | 打印一个字符串 |
\n | 换行 |
1.1.4 read_column_numders函数
在函数声明的数组参数中,不指定数组长度的这种格式是正确的,如果确实需要数组的长度,它的值必须作为一个单独的参数传递给函数。C语言中形式参数的名字和实际参数的名字并没有什么关系,可以相同,也可不同。
scanf函数从标准输入读取字符并根据字符串对他们进行转换——类似于printf函数的逆操作。scanf函数的返回值是函数成功转换并存储于参数中的值得个数。我们需要在参数前加上一个“&”符号,因为数组下标选择的是一个单一的数组元素,他是一个标量。
常用scanf格式代码
格式 | 含义 | 变量类型 |
%d | 读取一个整型值 | int |
%ld | 读取一个常整型值 | long |
%f | 读取一个实型值(浮点型) | float |
%lf | 读取一个双精度实型值 | double |
%c | 读取一个字符 | char |
%s | 从输入中读取一个字符串 | char型数组 |
int ch;
ch = getchar;
while ( ch != EOF && ch != '\n')
ch = getchar();
为什 么ch被声明为整型,而事实上需要它来读取字符?因为EOF是一个整型值,它的位数比字符类型要多,把ch声明为整型可以防止从输入读取的字符意外地被解释为EOF.但同时,这也意味着接受字符的ch必须足够大,足以容纳EOF.
2.基本概念
2.1环境
2.1.1翻译
目标代码——链接器——预处理器——解析——优化器
一、文件名约定
C源代码通常保存以.c扩展名的文件中。由#include指令包含到C源代码的文件被称为头文件,通常以.h为扩展名。在UNIX系统中,它们的扩展名是.o,在MS_DOS系统中,它们的扩展名是.obj.
二、编译和链接
在绝大多数UNIX系统中,C编译器被称为cc,它可以用多种方式来调用。
1.编译并链接一个完全包含与一个源文件的C程序:
cc program.c
这条命令产生一个称为a.out的可执行程序。中间会产生一个名为program.o的目标文件,但它在链接过程完成后会被删除。
2.编译并链接几个C源文件:
cc main.c sort.c lookup.c
当编译的源文件超过一个小时,目标文件便不会被删除。这就允许你对程序进行修改后,只对那些进行改动的源文件进行重新编译,如下一条命令所示。
3.编译一个C源文件,并把它和现存的目标文件链接在一起:
cc main.o lookup.o sort.c
4.编译单个C源文件,并产生一个目标文件,以后进行链接:
cc -c progrom.c
5.编译几个C源文件,并为每个文件产生一个目标文件:
cc -c main.c sort.c lookup.c
6.链接几个目标文件:
cc main.o sort.o lookup.o
上面那些可以产生可执行程序的命令均可加上“-o name”这个选项,它可以使链接器把可执行程序保存在“name”文件中,而不是“a.out”.在缺省的情况下,链接器在标准C函数库中查询。如果在编译时加上“-lname”标志,链接就会同时在“name”的函数库中进行查找。这个选项应出现在命令的最后。
2.1.2 执行
程序载入到内存——执行开始,调用main函数——执行程序代码——终止程序
2.2. 词法规则
2.2.1 字符
标准没有规定C环境必须使用哪些特定的字符集,但他规定字符集必须包括所有的大写和小写字母,数字0到9,以及这些符号:
! " # % ' ( ) * + , - . / : ; < > = ? [ ] \ ^ _ { } | ~
换行符也可以是一串字符,它们被当作单个字符处理。
标准还定义了几个三字母词,就是几个字符的序列合起来表示一个字符。以下是一些三字母词及它们所表示的字符。
??( [ ??< { ??= #
??) ] ??> } ??/ \
??! | ??' ^ ??- ~
如果在一些上下文环境中想使用某个特定的字符,但无法如愿以偿,这时K&R C定义了转义序列或字符转义克服这个难题。
\? 在书写连续多个问号时使用,防止他们被解释为三字母词。
\" 用于表示一个字符串内部的双引号。
\' 用于表示字符常量 ' .
\\ 用于表示一个反斜杠,防止它被解释为一个转义序列符
K&R C:
\a +警告字符。
\b 退格键
\f 进纸字符
\n 换行符
\r 回车符
\t 水平制表符
\v 垂直制表符
\ddd add表示1~3个八进制数字
\xddd xddd表示1~3个十六进制数
2.2.2 注释
C语言的注释以字符/*开始,以字符*/结束,中间可以包含除*/之外的任何字符。一个注释可能跨越多行,但不能签套在另一个注释中。
2.2.3 自由形式的源代码
C 是一种自由形式的语言,没有规定神魔地方可以书写语句,一行可以出现多少条语句,什么地方应该出现空白出现多少空白等。
2.2.4 标识符
标识符就是变量、函数、类型等的名字。它们由大小写字母(区分大小写)、数字、和下划线组成,但不能以数字开头。下列C语言关键字是被保留的,他们不能作为标识符使用:
auto do goto signed unsigned
break doubl e if sizeof void
case else int static volatile
char enum long struct volatile
const extern register switch
continue float return typedef
default for short union
2.2.5 程序的形式
一个C程序可能保存在一个或多个源文件中。虽然一个原文件可以包含超过一个函数,但每个函数都必须完整的出现于同一个源文件中,一个C源文件应该包含一组相关的函数。