C/C++实践进阶之道:写给程序员看的编程书
上QQ阅读APP看书,第一时间看更新

6-7 成为C程序员你还需要知道的事情

除了前面的基础知识,你还需要掌握这些C语言中比较专业的知识。

1.名字的重要性

在程序中经常发现许多以下画线开头的变量和函数名,例如:_dos_getdrive或_chmod。一般只在DOS环境中才使用这样的变量和函数。如果编写的程序将在DOS、Windows、Macintosh、UNIX或其他一些操作系统下运行,最好不要使用这样的函数,因为它们很可能在其他系统中不能用。这样,当要把程序从DOS转移到其他操作系统上时,必须重新编程。一个函数有两种命名(implementation),一种是带下画线的(_chmod),另一种是不带下画线的(chmod)。作为规则,应使用不带下画线的变量和函数,在本例中是chmod。

2.C语言区分大小写字母

当输入程序时,必须记住在C语言中大小写字母是区别对待的。作为一个规则,大多数C命令使用小写字母,大多数常量使用大写字母,而大多数变量使用的是大小写字母混合。在C程序中,小写字母的应用极为广泛。在下面的程序uppererr.c中,因为使用的是Main,而非C程序中所用的main,所以该程序不能编译成功:

当编译程序uppererr.c时,Turbo C编译器将显示如下消息:

Link error:Undefined suymbol _main module TURBO_C COS.ASM

Turbo C编译器返回的这条相对没有什么意义的消息是因为使用了Main的结果。在这种情况下,只需将Main改为main,重新编译并执行该程序即可。

3.理解分号的作用

在C程序中,我们会发现分号经常被使用。C程序中的分号有着特殊的意义。大家都知道,程序是计算机所要执行的指令集。使用这些指令时,必须用分号来分隔语句。随着程序变得越来越复杂,可能一行放不下一个语句。当C编译器检查程序时,它使用分号将相邻的语句分开。C语言的语法定义了分号的用法。如果忽略了分号的用法,将会出现语法错误,程序不能通过编译。

另外,我们经常在某一行代码中直接用一个“;”号,甚至调试的时候,连续几行都是“;”号,这是为了期待一个程序延时delay的作用,简单来说,就是让程序CPU空转一下,等待一下,看一下会有什么情况发生。

4.进一步了解连接器

编译C程序时,另一个被称作连接器的程序将程序语句和预定义例程连接起来(编译器提供的),将目标文件转化为可执行文件。如同编译过程可检测到错误一样,连接程序也可能检测到错误。举个例子,在下面的程序no_print.c中,使用错误的print来代替printf:

由于no_print程序并未违反C语法规则,它可以顺利通过编译,生成一个OBJ文件。但Turbo C却会因为未定义的print语句而显示如下的错误信息:

Error:Funcy\tion 'print'should have a prototype in function main()

因为C译器不提供名为print的函数,连接器不能生成可执行程序no_print.exe。相反,连接器将显示如上所示的错误信息。编辑源文件有,改正错误,将print改为printf,并重新编译、连接程序。

5.寄存器类型标识符

变量是与程序关联的内存单元的名字。定义一个变量时,C编译器将分配内存以存储变量的值。当程序必须存储变量时,CPU访问内存要占用一定的时间,有时可让编译器把变量存储在寄存器中(驻留于CPU本身中)以提高程序的性能。因为数值存储在寄存器中时,编译器存储该数值的速度大大加快,所以程序的执行速度也会更快。寄存器(register)类型标识符可通知编译器尽量把变量存储在寄存器中。因为CPU中寄存器的数目有限,编译器不可能让某个变量长期占用一个寄存器,所以编译器只能尽量把变量保存在寄存器中。下列语句说明了register类型标识符的使用方法:

对于程序经常存储到的变量应当使用register标识符,例如程序每次循环都必须访问的变量loop。

6.多赋值运算符

如前所述,C使用等号(=)作为赋值运算符。一般情况下,C程序在不同的行给变量赋值,如下所示:

如果想给多个变量赋相同的值,C语言允许同时完成这些赋值操作,如下所示:

count=sum=value=0;

当C遇到多赋值运算符时,它是从右至左赋值的。作为一条规则,多赋值运算符只能用来初始化变量。如果在更复杂的操作中使用这种方法,将降低程序的可读性。例如下列程序将输入字符的大写形式赋给两个变量:

ltr_save=letter=toupper(getchar());

7.把变量的值赋给另一种类型的变量

类型定义了变量的可存储数值,以及计算机对该数据进行的操作。C语言提供了四种基本数据类型(整型、浮点型、字符型和双精度型)。有时可能需要将一个整型变量的值赋给浮点型变量,或相反。作为一条普遍的规律,可以成功地把整型变量的值赋给浮点型变量。但如果要把浮点型变量的值赋给整型变量,那就得小心了。大部分编译器将截除浮点型数值的小数部分。而另一些编译器则可能进行四舍五入,而不是截尾(这意味着,当数值的小数部分大于0.5时,这两种编译器转换所得的数值将是不同的)。如果想确保程序把一个浮点型数转换成整型数的值每次都一样,需要使用ceil floor函数,这两个函数将在后面的部分讲到。

8.赋给十六进制或八进制值

有些程序有时可能需要使用八进制或十六进制数值。这时,应告诉编译器用户将使用非十进制的数值。如果使用以0(零)开头的数值例如077,C编译器将把它当作八进制看待。类似地,如果使用以0x开头的数值,例如0xFF,编译器将把它当作十六进制看待。下列语句说明了如何使用八进制和十六进制常量:

int octal_value=0227;

int hex_value=0xFF0;