清华大学出版社 TSINGHUA UNIVERSITY PRESS 第16章常见错误和程序调试 16.1常见错误分析 162程序调试
第16章 常见错误和程序调试 16.1 常见错误分析 16.2 程序调试
清华大学出版社 TSINGHUA UNIVERSITY PRESS 要真正学好C、用好C并不容易,“灵活”固然是 好事,但也使人难以掌握,尤其是初学者往往出 了错还不知怎么回事。C编译程序对语法的检查 不如其他高级语言那样严格(这是为了给程序人员 留下“灵活”的余地)。因此,往往要由程序设计 者自己设法保证程序的正确性。调试一个C程序 要比调试一个 PASCAL或 FORTRAN程序更困难 些。需要不断积累经验,提高程序设计和调试 程序的水平。 C语言有些语法规定和其他高级语言不同,学习 过其他高级语言的读者往往按照使用其他高级语 言的习惯来写C程序,这也是出错的一个原因
• 要真正学好C、用好C并不容易,“灵活”固然是 好事,但也使人难以掌握,尤其是初学者往往出 了错还不知怎么回事。C编译程序对语法的检查 不如其他高级语言那样严格(这是为了给程序人员 留下“灵活”的余地)。因此,往往要由程序设计 者自己设法保证程序的正确性。调试一个C程序 要比调试一个PASCAL或FORTRAN程序更困难 一些。需要不断积累经验,提高程序设计和调试 程序的水平。 • C语言有些语法规定和其他高级语言不同,学习 过其他高级语言的读者往往按照使用其他高级语 言的习惯来写C程序,这也是出错的一个原因
清华大学出版社 TSINGHUA UNIVERSITY PRESS 161常见错误分析 下面将初学者在学习和使用C语言(不包括C+)时 容易犯的错误列举出来,以起提醒的作用。这些 内容在以前各章中大多已谈到,为便于查阅,在 本章中集中列举,供初学者参考,以此为鉴。 (1)忘记定义变量。如: mant {x=3: printf("%dⅦn",x+y);
16.1 常见错误分析 • 下面将初学者在学习和使用C语言(不包括C++)时 容易犯的错误列举出来,以起提醒的作用。这些 内容在以前各章中大多已谈到,为便于查阅,在 本章中集中列举,供初学者参考,以此为鉴。 • (1) 忘记定义变量。如: main( ) {x=3; y=6; printf("%d\n " ,x+y); }
清华大学出版社 TSINGHUA UNIVERSITY PRESS C要求对程序中用到的每一个变量都必须定义其 类型,上面程序中没有对xy进行定义。应在函 数体的开头加intx,y;这是学过BASC和 FORTRAN语言的读者写C程序时常见的一个错误。 在 BASIC语言中,可以不必先定义变量类型就可 直接使用。在 FORTRAN中,未经定义类型的变 量按隐含的IN规则决定其类型,而C语言则要求 对用到的每一个变量都要在本函数中定义(除非已 定义为外部变量)。 (2)输入输出的数据的类型与所用格式说明符不 致 例如,若a已定义为整型,b已定义为实型
• C要求对程序中用到的每一个变量都必须定义其 类型,上面程序中没有对x、y进行定义。应在函 数体的开头加int x,y;这是学过BASIC和 FORTRAN语言的读者写C程序时常见的一个错误。 在BASIC语言中,可以不必先定义变量类型就可 直接使用。在FORTRAN中,未经定义类型的变 量按隐含的I-N规则决定其类型,而C语言则要求 对用到的每一个变量都要在本函数中定义(除非已 定义为外部变量)。 • (2) 输入输出的数据的类型与所用格式说明符不一 致。 • 例如,若a已定义为整型,b已定义为实型
清华大学出版社 TSINGHUA UNIVERSITY PRESS a=3;b=4.5 printf(of %d\n",a, b); 编译时不给出出错信息,但运行结果将与原意不 符,输出为 ·0.00000016402 ·它们并不是按照赋值的规则进行转换(如把4.5转 换成4),而是将数据在存储单元中的形式按格式 符的要求组织输出(如b占4个字节,只把最后两个 字节中的数据按%d,作为整数输出)。 ·(3)未注意int型数据的数值范围。 一般微型计算机上使用的C编译系统,对一个整 型数据分配两个字节。因此一个整数的范围为
a=3;b=4.5; printf("%f %d\n",a,b); • 编译时不给出出错信息,但运行结果将与原意不 符,输出为 • 0.000000 16402 • 它们并不是按照赋值的规则进行转换(如把4.5转 换成4),而是将数据在存储单元中的形式按格式 符的要求组织输出(如b占4个字节,只把最后两个 字节中的数据按%d,作为整数输出)。 • (3) 未注意int型数据的数值范围。 • 一般微型计算机上使用的C编译系统,对一个整 型数据分配两个字节。因此一个整数的范围为
清华大学出版社 TSINGHUA UNIVERSITY PRESS -215~215-1,即-32768~32767。常见这样的程序 段: int num: num=89101; printf(od", num) 得到的却是23565,原因是89101已超过32767。两 个字节容纳不下89101,则将高位截去。见图161。 即将超过低16位的数截去。即将89101减去216(即 16位二进制所形成的模)。89101-6536=23565
-2 15~2 15 -1,即-32768~32767。常见这样的程序 段: int num; num=89101; printf("%d",num); • 得到的却是23565,原因是89101已超过32767。两 个字节容纳不下89101,则将高位截去。见图16.1。 即将超过低16位的数截去。即将89101减去216(即 16位二进制所形成的模)。89101-65536=23565
清华大学出版社 TSINGHUA UNIVERSITY PRESS 8901:0000000010101100000101 23565: 0101110000001101 图161 有时还会出现负数。例如 ·num=196607 输出得-1。因为196607的二进制形式为 ·00000000000000101111111111111111 ·去掉高位10,低16位的值是1(-1的补码是: 1111lllllllllll1) 对于超过整个范围的数,要用long型,即改为 long int num; num=89101
图16.1 • 有时还会出现负数。例如 • num=196607; • 输出得-1。因为196607的二进制形式为 • 00 00 00 00 00 00 00 1011 11 11 11 11 11 11 11 • 去掉高位10,低16位的值是-1(-1的补码是: 1111111111111111)。 • 对于超过整个范围的数,要用long型,即改为 • long int num; • num=89101;
清华大学出版社 TSINGHUA UNIVERSITY PRESS printf("oold", num) 请注意,如果只定义num为ong型,而在输出时 仍用“%d”说明符,仍会出现以上错误。 ·(4)输入变量时忘记使用地址符。如: scanf("%od%d",a, b) 这是许多初学者刚学习C语言时一个常见的疏忽, 或者说是习惯性的错误,因为在其他语言中在输 入时只需写出变量名即可,而C语言要求指明 “向哪个地址标识的单元送值”。应写成 scanf(%od %d", &a, &b); ·(5)输入时数据的组织与要求不符 用scan函数输入数据,应注意如何组织输入
• printf("%ld",num); • 请注意,如果只定义num为long型,而在输出时 仍用“%d”说明符,仍会出现以上错误。 • (4) 输入变量时忘记使用地址符。如: • scanf("%d%d",a,b); • 这是许多初学者刚学习C语言时一个常见的疏忽, 或者说是习惯性的错误,因为在其他语言中在输 入时只需写出变量名即可,而C语言要求指明 “向哪个地址标识的单元送值”。应写成 scanf("%d%d",&a,&b); • (5) 输入时数据的组织与要求不符。 • 用scanf函数输入数据,应注意如何组织输入
清华大学出版社 TSINGHUA UNIVERSITY PRESS 数据。假如有以下scan函数: scanf("%od%d", &a, &b); 有人按下面的方法输入数据: 3, 这是错的。数据间应该用空格来分隔。读者可以 用 printf("ood%d", a, b) ·来验证一下。应该用以下方法输入: ·34 如果 scanf函数为 scanf( %d, %d,&a, &b); 对scan函数中格式字符串中除了格式说明符外
数据。假如有以下scanf函数: • scanf("%d%d",&a,&b); • 有人按下面的方法输入数据: • 3,4 • 这是错的。数据间应该用空格来分隔。读者可以 用 • printf("%d%d",a,b); • 来验证一下。应该用以下方法输入: • 34 • 如果scanf函数为 • scanf("%d,%d",&a,&b); • 对scanf函数中格式字符串中除了格式说明符外
清华大学出版社 TSINGHUA UNIVERSITY PRESS 对其他字符必须按原样输入。因此,应按以下方 法输入 3,4 此时如果用“34”反而错了。还应注意,不能企图 用 scanf( input a &e b: %d, %od, &a, &b 想在屏幕上显示一行信息: · input a&b: 然后在其后输入a和b的值,这是不行的。这是由 于有的读者以为 scanf具有 BASIC语言中的 IINPUT 语句的功能(先输出一个字符串,再输入变量的值) 如果想在屏幕上得到所需的提示信息,可以另加 个prin函数语句:prin" input a&b:");
对其他字符必须按原样输入。因此,应按以下方 法输入: • 3,4 • 此时如果用“34”反而错了。还应注意,不能企图 用 • scanf("input a & b:%d,%d",&a,&b); • 想在屏幕上显示一行信息: • input a & b: • 然后在其后输入a和b的值,这是不行的。这是由 于有的读者以为scanf具有BASIC语言中的INPUT 语句的功能(先输出一个字符串,再输入变量的值)。 如果想在屏幕上得到所需的提示信息,可以另加 一个printf函数语句:printf("input a & b:");