2.1一定要将常量定义成符号常量吗?
答:不一定。但这是提倡的编程风格,其好处是:语义更明确;提高程序的维护性;便于保持数据的一致性。
2.2为什么说对字符串常量的修改是极其危险的?如果必须要修改,该怎么办?
答:ANSI C认为对字符串常量的修改,其结果未定义。这是因为,不同的字符串可能相邻地存储在一片连续的空间;相同的字符串可能共用同一空间,这就使得对串A的修改波及到串B。一个串要被修改,采用字符数组存储是安全的。
2.3用#define定义的符号常量和用const定义的变量有什么异同?为什么要用const修饰变量?
答:两者都可以当作常量使用。但是,符号常量只能在语法上允许常量出现的地方使用;const常量只能用于允许使用变量的地方。定义const变量的目的是明确地告诉程序阅读者,这个变量的值是不能被修改的。当然,如果企图修改它,编译器会报告错误。符号常量能提高程序的可读性和维护性,const常量可增强数据的安全性。
2.4用#define定义符号常量有什么好处?
答:至少有两个明显的好处:易读性更好;维护更方便且不易出错。
2.5变量定义的作用是什么?
答:它告诉编译器所定义的变量名和类型,要求按指定的类型分配空间。
2.6既然枚举型变量事实上就是整型变量,那么在应用中是否可以将枚举型变量当作整型变量来使用。
答:从语法的角度看是合法的。但如果将枚举变量无差别地混同于整型变量,枚举类型的定义就变得毫无意义了。例如:
enum Color{ RED,BLUE,GREEN,WHITE,BLACK } mycolor;
mycolor = RED;
如果将mycolor当作整型变量输出,其结果为0。颜色为0,它是什么颜色呢?
2.7什么是溢出?整数溢出与浮点数溢出有什么区别?
答:当发生整数溢出时,这个变量会被“反卷”成负数,产生错误的结果;当发生浮点数溢出时,这个变量的值会被设为代表无穷大的常数inf。
2.8如果整数类型在正常情况下是带符号的,那么关键字signed的目的何在呢?
答:由于字符在本质上是(小)整型值,但ANSI C标准并没有规定缺省的char究竟是signed char还是unsigned char。这意味着不同系统上的char可能拥有不同范围的值,所以,只有当程序中的char变量的值位于它们二者的交集中,这个程序才是可移值的。
显然,在这种情况下,如果把char定义为signed或unsigned,可提高这类程序的可移植性,能确保在不同系统的机器中在字符是否为有符号值方面保持一致。
2.9数值溢出错是编译错还是运行错?为什么说这种错误更严重?
答:这是一种在运行时出现的错误。其严重性在于编译器不能捕获它,调试者也往往难以发现和定位问题所在,甚至程序崩溃了,还不知问题出在哪里。
2.10下列代码有什么错误?
enum fruit {apple,orange,lemon,tomato};
enum vegetable {potato,carrot,tomato};
答:第二个enum试图重新定义常量tomato。
2.11 以下两条语句有何不同:
char ch = 'A';
char ch = 65;
答:没有什么不同。
2.12指出下列内容哪些是C语言的整型常量,哪些是实型常量,哪些两者都不是。
1E-4 A423 -E-31 0xABCL,32E31 087
0xL 0x12.5 11E 056L 0123.,0
答:整型常量:1E-4 087 056L
实型常量:.32E31 0123.,0
2.13 在你的机器上运行下面的程序,分析它的输出结果,解析其原因。
#include<stdio.h>
int main()
{
int n = 10;
while(n>0) /* 当n>0时输出n的值 */
printf("n = %d\n",n = n*n);
}
答:在Turbo C下运行后输出结果是:
n = 100
n = 10000
n = -7936
可见,由于程序中用n*n不断地改变了整型变量n的值,使得当n的值超出了n的表示范围时,其值被“反卷”为负数,从而结束程序。由此可见,整型数超出表示范围时,该编译器并不视为错误。
2.14 在你的机器上运行下面的程序,分析它的输出结果,解释其原因。
#include<stdio.h>
int main()
{
float x = 10.0;
while (x>0)
printf("x = %g\n",x=x*x);
}
答:在Turbo C下运行后输出结果是:
x = 100
x = 10000
x = 1e+08
x = 1e+16
x = 1e+32
Floating point error:Overflow.
可见,由于程序中用x*x不断地改变了实型变量x的值,使得当x的值超出了x的表示范围时,报告错误,从而结束程序。由此可见,实型数超出表示范围时,该编译器视为错误,并且非正常终止程序运行。
2.15 分析下列程序的输出结果:
#include<stdio.h>
int main()
{
char ch = 'A';
printf("char(%c) = %c,A = %c\n",ch,ch,'A');
printf("int(%c) = %d,A = %d\n",ch,ch,'A');
}
答:在Turbo C下运行后输出结果是:
char(A) = A,A = A
int(A) = 65,A = 65
输出说明char型量可以与int型量一起参加运算。
2.16 分析下列程序的输出结果,解释其原因。
#include<stdio.h>
int main()
{
int a=10;
int *iptr=&a;
char *sptr="String";
int *ptr=0;
printf("a = %d\t*iptr = %d\n",a,*iptr );
printf("s = %s\n",sptr);
printf("*ptr = %d\n",*ptr);
}
答:在Turbo C下运行后输出结果是:
a = 10,*iptr = 10
s = String
*ptr = 283
因为指针iptr和sptr分别指向变量a和串“String”,所以程序输出的前两行是正确的。由于指针ptr被初始化为空指针,它没有指向一个确定的目标,所以程序输出的第三行是没有意义的。可见,该编译器对空指针的直接引用并不认为是一种错误,这显然潜伏着危险。
2.17 仿照习题2.15编写并运行一程序,打印元音字母字符A、B和Z及数字字符0、1和9的ASCII码。
答:可编程序如下:
#include<stdio.h>
int main()
{
printf("char(A) = %d,B = %d,Z = %d\n",'A','B','Z');
printf("digit(0) = %d,1 = %d,9 = %d\n",'0','1','9');
}
答:不一定。但这是提倡的编程风格,其好处是:语义更明确;提高程序的维护性;便于保持数据的一致性。
2.2为什么说对字符串常量的修改是极其危险的?如果必须要修改,该怎么办?
答:ANSI C认为对字符串常量的修改,其结果未定义。这是因为,不同的字符串可能相邻地存储在一片连续的空间;相同的字符串可能共用同一空间,这就使得对串A的修改波及到串B。一个串要被修改,采用字符数组存储是安全的。
2.3用#define定义的符号常量和用const定义的变量有什么异同?为什么要用const修饰变量?
答:两者都可以当作常量使用。但是,符号常量只能在语法上允许常量出现的地方使用;const常量只能用于允许使用变量的地方。定义const变量的目的是明确地告诉程序阅读者,这个变量的值是不能被修改的。当然,如果企图修改它,编译器会报告错误。符号常量能提高程序的可读性和维护性,const常量可增强数据的安全性。
2.4用#define定义符号常量有什么好处?
答:至少有两个明显的好处:易读性更好;维护更方便且不易出错。
2.5变量定义的作用是什么?
答:它告诉编译器所定义的变量名和类型,要求按指定的类型分配空间。
2.6既然枚举型变量事实上就是整型变量,那么在应用中是否可以将枚举型变量当作整型变量来使用。
答:从语法的角度看是合法的。但如果将枚举变量无差别地混同于整型变量,枚举类型的定义就变得毫无意义了。例如:
enum Color{ RED,BLUE,GREEN,WHITE,BLACK } mycolor;
mycolor = RED;
如果将mycolor当作整型变量输出,其结果为0。颜色为0,它是什么颜色呢?
2.7什么是溢出?整数溢出与浮点数溢出有什么区别?
答:当发生整数溢出时,这个变量会被“反卷”成负数,产生错误的结果;当发生浮点数溢出时,这个变量的值会被设为代表无穷大的常数inf。
2.8如果整数类型在正常情况下是带符号的,那么关键字signed的目的何在呢?
答:由于字符在本质上是(小)整型值,但ANSI C标准并没有规定缺省的char究竟是signed char还是unsigned char。这意味着不同系统上的char可能拥有不同范围的值,所以,只有当程序中的char变量的值位于它们二者的交集中,这个程序才是可移值的。
显然,在这种情况下,如果把char定义为signed或unsigned,可提高这类程序的可移植性,能确保在不同系统的机器中在字符是否为有符号值方面保持一致。
2.9数值溢出错是编译错还是运行错?为什么说这种错误更严重?
答:这是一种在运行时出现的错误。其严重性在于编译器不能捕获它,调试者也往往难以发现和定位问题所在,甚至程序崩溃了,还不知问题出在哪里。
2.10下列代码有什么错误?
enum fruit {apple,orange,lemon,tomato};
enum vegetable {potato,carrot,tomato};
答:第二个enum试图重新定义常量tomato。
2.11 以下两条语句有何不同:
char ch = 'A';
char ch = 65;
答:没有什么不同。
2.12指出下列内容哪些是C语言的整型常量,哪些是实型常量,哪些两者都不是。
1E-4 A423 -E-31 0xABCL,32E31 087
0xL 0x12.5 11E 056L 0123.,0
答:整型常量:1E-4 087 056L
实型常量:.32E31 0123.,0
2.13 在你的机器上运行下面的程序,分析它的输出结果,解析其原因。
#include<stdio.h>
int main()
{
int n = 10;
while(n>0) /* 当n>0时输出n的值 */
printf("n = %d\n",n = n*n);
}
答:在Turbo C下运行后输出结果是:
n = 100
n = 10000
n = -7936
可见,由于程序中用n*n不断地改变了整型变量n的值,使得当n的值超出了n的表示范围时,其值被“反卷”为负数,从而结束程序。由此可见,整型数超出表示范围时,该编译器并不视为错误。
2.14 在你的机器上运行下面的程序,分析它的输出结果,解释其原因。
#include<stdio.h>
int main()
{
float x = 10.0;
while (x>0)
printf("x = %g\n",x=x*x);
}
答:在Turbo C下运行后输出结果是:
x = 100
x = 10000
x = 1e+08
x = 1e+16
x = 1e+32
Floating point error:Overflow.
可见,由于程序中用x*x不断地改变了实型变量x的值,使得当x的值超出了x的表示范围时,报告错误,从而结束程序。由此可见,实型数超出表示范围时,该编译器视为错误,并且非正常终止程序运行。
2.15 分析下列程序的输出结果:
#include<stdio.h>
int main()
{
char ch = 'A';
printf("char(%c) = %c,A = %c\n",ch,ch,'A');
printf("int(%c) = %d,A = %d\n",ch,ch,'A');
}
答:在Turbo C下运行后输出结果是:
char(A) = A,A = A
int(A) = 65,A = 65
输出说明char型量可以与int型量一起参加运算。
2.16 分析下列程序的输出结果,解释其原因。
#include<stdio.h>
int main()
{
int a=10;
int *iptr=&a;
char *sptr="String";
int *ptr=0;
printf("a = %d\t*iptr = %d\n",a,*iptr );
printf("s = %s\n",sptr);
printf("*ptr = %d\n",*ptr);
}
答:在Turbo C下运行后输出结果是:
a = 10,*iptr = 10
s = String
*ptr = 283
因为指针iptr和sptr分别指向变量a和串“String”,所以程序输出的前两行是正确的。由于指针ptr被初始化为空指针,它没有指向一个确定的目标,所以程序输出的第三行是没有意义的。可见,该编译器对空指针的直接引用并不认为是一种错误,这显然潜伏着危险。
2.17 仿照习题2.15编写并运行一程序,打印元音字母字符A、B和Z及数字字符0、1和9的ASCII码。
答:可编程序如下:
#include<stdio.h>
int main()
{
printf("char(A) = %d,B = %d,Z = %d\n",'A','B','Z');
printf("digit(0) = %d,1 = %d,9 = %d\n",'0','1','9');
}