3.6 参数和易犯的错误

有必要重复并深入介绍一下本章前面提到的关于printf()的使用。传递给函数的信息被称为参数。例如,函数调用printf(“Hello, pal.”)包含一个参数“Hello,pal.”。用双引号引起来的一串字符称为字符串,详见第4章。现在要指出的是,不论包含多少字符和标点符号,一个字符串只是一个参数。

与之类似,函数调用scanf(“%d”, &weight)包含两个参数:“%d”和&weight。C用逗号来隔开函数调用中的多个参数。printf()和scanf()函数比较特殊,其参数数目可以不受限制。例如,我们曾经使用1个、2个,甚至3个参数调用printf()函数。程序需要知道参数的数目才能正常工作。这两个函数通过第一个参数确定后续参数的个数,方法是第一个参数字符串中的每个说明符对应了后面的一个参数。例如,下面的语句包含两个格式说明符:%d和%d。

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

printf (“%d cats ate %d cans of tuna\n”, cats, cans);

这告诉程序后面还有2个参数,确实有2个:cats和cans。

程序员要保证格式说明符的数目同后面的参数数目相同。现在C通过一种函数原型机制检查函数调用是否使用了正确数目及类型的参数,但是这对printf()和scanf()函数不起作用,因为它们的参数数目是变化的。如果参数数目存在问题,会出现什么情况?例如,假设您编写了程序清单3.9中的程序。

程序清单3.9 badcount.c程序

阅读 ‧ 电子书库

Microsoft Visual C++ 7.1 (Windows XP)的输出结果如下:

4

4 34603777

0 0.000000

在Digital Mars(Windows XP)中结果为:

4

4 4239476

0 0.000000

下面是Macintosh机Metrowerks CodeWarrior Pro 5的输出结果:

4

4 3327456

1075052544 0.000000

注意,使用%d显示float值不会把该float值转换为近似的int值,而是显示垃圾值。与之类似,使用%f显示int值也不会把该int值转换为浮点值。而且,参数的数目不足和类型不匹配所造成的结果也将随平台不同而不同。

我们所尝试的编译器都没有对上面的代码提出异议,在运行程序时也不会报告错误。没错,有的编译器可能会捕捉到这种错误,但是C标准并没有要求它们这么做。因此,计算机在运行时可能不捕捉这种类型的错误。由于程序运行正常,所以您也很难觉察这样的错误。如果程序没有显示期望的值或显示了异常的值,则应当检查printf()函数参数个数是否正确。顺便说一下,UNIX语法检查程序lint比UNIX编译器更为严格,它会检查出printf()的参数错误。