Skip to content

U2

211275022田昊东

13、

x y
第一步 a a^b
第二步 a^a^b=b a^b
第三步 b b^a^b=a

14、

  • 当len为奇数时,处于数组中间位置的数会被置0,可能会导致结果不正确
  • 最后一次循环中left=right=(len-1)/2
  • 最后一次调用后会将a[(len-1)/2]置零
  • 修改循环条件for(left=0;left<right;left++.right--)

15、

x y x^y x&y x|y ~x|~y x&!y x&&y x||y !x||!y x&&~y
0x5F 0xA0 0xFF 0x00 0xFF 0xFF 0x00 0x01 0x01 0x00 0x01
0xC7 0xF0 0x37 0xC0 0xF7 0x3F 0x00 0x01 0x01 0x00 0x01
0x80 0x7F 0xFF 0x00 0xFF 0xFF 0x00 0x01 0x01 0x00 0x01
0x07 0x55 0x5E 0x01 0x5F 0xFE 0x00 0x01 0x01 0x00 0x01

16、

  1. x&=0xFF<<(n-8);
  2. x&=0xFF;
  3. x^=~0;x&=~0xFF;
  4. x|=0xFF;

17、

  1. b8 01 00 00
  2. 转化为二进制补码表示:00000000 00000000 00000001 10111000
  3. 转化为真值:440
  4. 14
  5. 转化为二进制补码表示:00010100
  6. 转化为真值:20
  7. 58 fe ff ff
  8. 转化为二进制补码表示:11111111 11111111 11111110 01011000
  9. 转换回原码10000000 00000000 00000001 10101000
  10. 转化为真值:-424
  11. 74 fe ff ff
  12. 转化为二进制补码表示:11111111 11111111 11111110 01110100
  13. 转换回原码10000000 00000000 00000001 10001100
  14. 转化为真值:-396
  15. 44
  16. 转化为二进制补码表示:01000100
  17. 转化为真值:68
  18. c8 fe ff ff
  19. 转化为二进制补码表示:11111111 11111111 11111110 11001000
  20. 转换回原码10000000 00000000 00000001 00111000
  21. 转化为真值:-312
  22. 10
  23. 转化为二进制补码表示:00010000
  24. 转化为真值:16
  25. 0c
  26. 转化为二进制补码表示:00001100
  27. 转化为真值:12
  28. ec fe ff ff
  29. 转化为二进制补码表示:11111111 11111111 11111110 11101100
  30. 转换回原码10000000 00000000 00000001 00010100
  31. 转化为真值:-276
  32. 20
    • 转化为二进制补码表示:00100000
    • 转化为真值:32

18、

  • 当str2的长度大于str1的长度时会发生错误。
  • 因为strlen(str2)-strlen(str1)会得到一个无符号整数,因此0也会被提升为无符号整数,因此strlen(str2)-strlen(str1)>0恒成立,无法正确判断。
  • 应该直接比较return strlen(str1)>strlen(str2);

21、

  • arith函数的目的是计算x*M+y/N
  • 由于当乘除法可以转化为左右移操作时,系统会自动对其进行转化,来提高效率
  • optarith中先将x左移4位然后又减去一个原先的x,这相当于x*=15;然后对y右移2位,这相当于y/=4
  • 所以:M=15,N=4

30、

int ch_mul_overflow(int x,int y)
{
    long long num=(long long)x*y;
    int t=(num>>31)&1;
    for(int i=0;i<32;i++)
    {
        if(((num>>(32+i))&1)!=t)
            return 1;
    }
    return 0;
}

31、

  • 不能修复溢出漏洞,由于malloc函数接收的参数为size_t类型(unsigned int),即使使用unsigned long long存储数据,在调用malloc进行数据传递时也会被转化为unsigned int类型。无法解决整数溢出漏洞。

  • 修改方案:

  • 由于malloc函数只能传入size_t类型参数,也就说发生溢出的原因是需要分配的空间大于malloc能够分配的内存的上限,因此可以在分配空间时先判断能否满足需求,如果不能则返回-1.

  • c //在2、3行之间插入以下判断 unsigned long long sum=count*(unsigned long long)sizeof(int); if(sum>0xffffffff) return -1;

34、

  1. 不永真:x=0x0000C000
  2. 不永真:x=0x80000000
  3. 永真:
  4. 当x<0时自然为真
  5. 当x>=0时,由于取-x一定不会发生溢出,因此一定有-x<=0
  6. 因此永真
  7. 不永真:x=0x80000000
  8. 不用真:由于!=的优先级高于&所以相当于x&0||(x<<28)<0
  9. x=0
  10. 不永真:x=0x80000000 y=0
  11. 不永真:x=0xffffffff y=1
  12. 永真:
  13. (int)(ux-uy)=[x-y]=[x]+[-y]=[-y]+[x]=[-y+x]=[-(y-x)]=-(y-x)
  14. 故该式永真
  15. 永真:因为右移是向-inf方向舍入,故不等式一定成立
  16. 永真:因为*4等价于左移2位,*8等价于左移3位
  17. 不永真:x=-1 y=-1
    • 左侧为0而右侧为-1
    • 这是因为负数右移没有加偏移量,会导致向-inf舍入
  18. 永真:虽然结果在高位上可能不同,但在低位上是完全相同的,由于结果只取低位因此该式恒成立。
  19. 永真:alu加法器在进行运算时不区分是否有符号,因此等式左右的结果是相同的,恒成立。
  20. 永真:x*~y+ux*uy=x(-y-1)+xy=-xy-x+xy=-x

35、

  1. 永真:浮点数的符号位独立存储不会受到溢出的任何影响
  2. 不永真:因为int转化为float的过程中会造成精度的损失,是等式不一定成立
  3. x=0x7fffffff
  4. 不永真:double的可表示范围比int大得多,可能int发生了溢出,而double没有
  5. x=y=0x7fffffff
  6. 永真:因为double的精度高于int,因此把int转化为double进行计算不会发生舍入,因此等式恒成立
  7. 不永真:三个int相乘可能超过了double的精度,需要进行舍入x=0x7ffffffa y=0x7ffffff2 z=0x7ffffff1
  8. 不永真:x=0 y=1