title: 收集在牛客网上的一些错题。(2018年3月13号更新)

1、一个C++语言程序是由 函数组成。说法是否正确?

这个说法是正确的。

解释:一个C++程序是由一个或多个函数所组成,即使是最简单的程序,也必须有一个 main 函数。该函数是程序执行的 起点 和 终点 。C++中,函数不允许嵌套定义 ,允许嵌套调用 。

2、完成将累加器AL清零,并使进位标志CF清零,下面错误的指令是( A )

A MOV AL,00H

B AND AL,00H

C XOR AL,AL

D SUB AL,AL

解析:AND OR XOR只要使用则CF标志位即为0,MOV不影响标志位,sub没有进位,cf为0

3 解析下面的程序:


void swap_int(int *a,int *b){
   *a=*a+*b;
   *b=*a-*b;
   *a=*a-*b;
   }

解析:结果正确,即使会溢出.

详细解析:

链接来源:牛客网


设整形变量*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 是成立的。因此尽管溢出了,但仍能正确交换。

4、下面哪一个不是动态链接库的优点?

##

5、以下哪种方式,在读取磁盘上多个顺序数据块时的效率最高?

(1)程序直接访问方式跟循环检测IO方式,应该是一个意思吧,是最古老的方式。CPU和IO串行,每读一个字节(或字),CPU都需要不断检测状态寄存器的busy标志,当busy=1时,表示IO还没完成;当busy=0时,表示IO完成。此时读取一个字的过程才结束,接着读取下一个字。

(2)中断控制方式:循环检测先进些,IO设备和CPU可以并行工作,只有在开始IO和结束IO时,才需要CPU。但每次只能读取一个字。

(3)DMA方式:Direct Memory Access,直接存储器访问,比中断先进的地方是每次可以读取一个块,而不是一个字。

(4)通道方式:比DMA先进的地方是,每次可以处理多个块,而不只是一个块。

6、下面哪一个不是动态链接库的优点?

1 静态链接库的优点

(1) 代码装载速度快,执行速度略比动态链接库快;

(2) 只需保证在开发者的计算机中有正确的.LIB文件,在以二进制形式发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题,可避免DLL地狱等问题。

2 动态链接库的优点

(1) 更加节省内存并减少页面交换;

(2) DLL文件与EXE文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性;

(3) 不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数;

(4)适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和测试。

3 不足之处

(1) 使用静态链接生成的可执行文件体积较大,包含相同的公共代码,造成浪费;

(2) 使用动态链接库的应用程序不是自完备的,它依赖的DLL模块也要存在,如果使用载入时动态链接,程序启动时发现DLL不存在,系统将终止程序并给出错误信息。而使用运行时动态链接,系统不会终止,但由于DLL中的导出函数不可用,程序会加载失败;速度比静态链接慢。当某个模块更新后,如果新模块与旧的模块不兼容,那么那些需要该模块才能运行的软件,统统撕掉。这在早期Windows中很常见。

这道题目容易弄错的地方就在于,把第二次选择当作整个游戏。如果跳过前面的排除,直接跳到第二次选择:你现有的和剩下的一个盒子中只有一个装了球。当然换或者不换获胜的概率都是 1/2,但是综合前面的情况来看,第二次选择 获胜 有两种情况:

  1. 不修改选择并获胜,表示第一次已经选对。概率为:1/3 * 1/2 = 1/6
  2. 修改选择并 获胜,表示第一次选错。概率为:2/3 * 1/2 = 2/6
    综上可知,第二次选择中修改选择后获胜的概率较大。
    注意, 这里的 2/6 并不是整个游戏中改选的获胜概率!第二次选择,胜负的概率各为 1/2,这里的 2/6 只是第二次选择中通过改选达到获胜的概率。
    那整个游戏中改选获胜的概率是多少呢?3 个盒子可能不容易看清,我们把问题改成:有 10 个盒子,选择完成之后移除 8 个空盒子。那么第一次选择的盒子有球的概率是 1/10,剩下 9 个盒子有球的概率是 9/10;移除 8 个空盒子相当于告诉你这 8 个盒子有球的概率为 0,但是 9个盒子有球的总概率为 9/10 是没有变的,这就表明剩下的那个盒子有球的概率是 9/10,如果改选这个盒子获胜的概率就是 9/10。同理,对于 3 个盒子,改选获胜的概率是 2/3,A 错。