C++学习(66)

来源:互联网 发布:幸运抽奖软件免费版 编辑:程序博客网 时间:2024/06/04 17:41

1 以下正确的是(B)

A在C语言中,逻辑真值和假值分别对应1和0

B关系运算符两边的运算对象可以是c语言中任意合法的表达式

C对于浮点变量x和y,表达式:x==运算非法的,会出现编译错误

D分支结构是根据算式表达式的结果来判断流程走向的


分析:

A 关系表达式和逻辑表达式的值 是布尔型:真或假(true or false),即0或1,c语言没有布尔类型,以0为假,非0即真。
B是合法的,语法正确,算法错误。
D分支结构的流程走向是根据表达式的值,并不仅仅是算式表达式的值。
 
2.分析下列程序
#include<iostream>  using namespace std;  int main() {    int a=2,c=5;    printf("a=%%d,b=%%d\n",a,c);    return 0;  } 
输出结果是 a=%d,b=%d
C 语言中用 "%%" 打印输出字符 "%", 所以 %%d, 输出为 %d 两个普通字符 , 而不是格式控制符 "%d" 的含义 , 所以打印结果为 C 

3.分析下列程序,输出结果是253.


#include<iostream>  using namespace std;  int main() {     unsigned char i=1;     i-=4;     printf("%d",i);     return 0;  } 


再举一例,我们来看整数-1在计算机中如何表示。

假设这也是一个int类型,那么:

1)、先取1的原码:00000000 00000000 00000000 00000001

2)、得反码:    11111111 11111111 11111111 11111110

3)、得补码:    11111111 11111111 11111111 11111111

可见,-1在计算机里用二进制表达就是全116进制为:0xFFFFFF

负数的二进制表示方法
 

4 若MyClass为一个类,执行Myclass a[4],*p[5];语句时会自动调用该类构造函数的次数的是 4.

分析:把MyClass a[4],*p[5];分开写;
MyClass a[4]; 
MyClass *p[5];
则a[4]是类数组,有4个对象,调用构造函数4次 
*p[5]是指针数组,也就是5个元素存放的是指向MyClass类型的对象的指针,没有初始化的指针为空,不指向任何对象,也不调用构造函数。 

 

好比你用自己定义的一个类去定义一个对象,它是会调用构造函数的,(Ps : A a).如果定义一个对象指针,它不会调用构造函数。(Ps :A *a). 
5.下列程序是:B结果正确,即使会溢出。
void swap_int(int *a,int *b) {      *a=*a+*b;      *b=*a-*b;      *a=*a-*b;  } 

A 结果不正确,因为会溢出,用位与方式就没问题  B 结果正确,即使会溢出 C结果正确,不会溢出                 D 其他选项正确
分析:设整形变量*a、*b的位表示为*a = n31n30 ··· n0,*b = m31m30 ··· m0
只有当*a > 0 && *b > 0 或 *a < 0 && *b < 0时才会发生溢出。两者类似,只证明均大于0时的情况。必须扩展额外一位才能够容纳正确的结果,'|'左边为扩展位。
*a = 0|0n30 ··· n0 = n30*230 +  n29*229 + ··· + n0*20 = N
*b = 0|0m30 ··· m0 = m30*230 +  m29*229 + ··· + m0*20 = M
若和溢出,则33位表示必为
*a + *b = 0|1b30 ··· b0 = -231 + b30*230 +  b29*229 + ··· + b0*20 =  2 31 + B ① 
计算机将得到的33位结果truncate回原来的32位,即丢弃第33位(0)变为:
*a + *b =    1b30 ··· b0 = -231 + b30*230 +  b29*229 + ··· + b0*20 = -2  31  + B ②
正确的真实值是①,溢出结果为②,可见溢出结果=真实值-2 32 
则*b = *a - *b = ② - *b =  ① - 232 - *b = *a + *b - 232 - *b = -232 + *a
最后一步,来看 -232 + *a  == *a 成立否?
0 < *a < 231, 则 -232 < -232 + *a < -231,和仍需要扩展1位方能表示:
*a    = 0|0n30 ··· n0 = n30*230 +  n29*229 + ··· + n0*20 = N
-232 = 1|0000 ··· 00
和的位表示为-232 + *a = 1|0n30 ··· n0 = n30*230 +  n29*229 + ··· + n0*20
同样,计算机把33位结果truncate回32位(丢弃第33位)得到:232 + *a =  0n30 ··· n0 = n30*230 +  n29*229 + ··· + n0*20 = *a
可见-232 + *a  == *a 是成立的。因此尽管溢出了,但仍能正确交换。
---分隔线---
写的比较繁琐,见谅
这道题首先得保证输入的两个参数不是指向同一个地址,否则,无论两个数如何,交换后的结果都将变为零,题目中没说明这一点。
此题可以参考《深入理解计算机》P58页习题2.30 
大致思路:即使会产生溢出,但是运算法则仍然成立,举个例子,假设int只有4bit,那么-8 + (-5) = -13(溢出), 实际结果为3,而3-(-8) = 11(依然溢出),实际结果是-5, 
所以,swap程序中的第二句: *b=*a-*b,相当于*b = *a+*b-*b;溢出并没有影响。 
 
 
6. 因为e是不断地除以2,所以调用次数应该是以2为底的对数!
int power(int b,int e) {     if(e==0) return 1;     if(e%2==0) return power(b*b,e/2);     return b*power(b*b,e/2);  }
Alogarithmic 对数的  
Blinear 线性的           
Cquadratic 二次方的  
Dexponential 指数的
7.字符串“HELLO”会被输出几次:4
int main() {  printf("hello");  fork();  printf("hello");  } 

分两点说吧:1.fork()函数会把它所在语句以后的语句复制到一个子进程里,单独执行。2.如果printf函数最后没有"\n",则输出缓冲区不会被立即清空,而fork函数会把输出缓冲区里的内容也都复制到子进程里。所以,父进程和子进程各输出2Hello,共4个。如果第一个printf("Hello");写成printf("Hello\n");,则只会输出3Hello,父进程2个,子进程1个。
print输出字符串如果不是一"\n"为结尾的话,就不会马上输出,而是保存在缓存区中。fork函数在创建子进程的时候会复制缓存区的数据。 
的面试题
下fork函数的总结