csapp---datalab

  • Csapp–datelab学习

  • bitXor

    题目

    /*

    • bitXor - x^y using only ~ and &
    • Example: bitXor(4, 5) = 1
    • Legal ops: ~ &
    • Max ops: 14
    • Rating: 1
      */

分析,解题过程和思路及学习

离散数学中异或(对称差),符号为⊕。

运算法则:a⊕b = (¬a ∧ b) ∨ (a ∧¬b)

其中非(¬)与非运算(~)对应,合取(∧)和与运算(&)对应,析取(∨)与或运算(|)对应。

由¬(A∨B)⇔¬A∧¬B(德摩根律)可知a⊕b = ¬(¬(¬a ∧ b) ∧ ¬(a ∧¬b))

对应可知计算机中a^b = ((~a & b) & ~(a & ~b))

代码

int bitXor(int x, int y) {
    return ~(~(~x & y) & ~(x & ~y));
}

tmin

题目

/*

  • tmin - return minimum two’s complement integer (返回最小二进制补码)
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 4
  • Rating: 1
    */

分析,解题过程和思路及学习

原码:最高位为符号位,0表示正数,1表示负数。

反码:正数的反码等于本身,负数的反码除符号位外,各位取反。

补码:正数的补码等于本身,负数的补码等于反码+1。

1000 0000:负0;

负0,实际是白占一坑,就把它用来表示-128了。

-128的原码 10000000 (-128,进位被舍去)

-128的反码 11111111(负数的非符号位取反)

-128的补码 11111111+ 1=10000000(反码+1),这里实际上真正相加的是11111111后面的7位,第1位是符号位始终不会变,所以,当进到第8位的时候,就表示溢出被舍弃。

所以最小的二进制补码为10000000,C语言中int类型占4字节,即32位,所以对1左移31位来构造最小补码。

代码

int tmin(void) {
    int a = 1;
    return a << 31;

}

isTmax

题目

/*

  • isTmax - returns 1 if x is the maximum, two’s complement number,and 0 otherwise
  • Legal ops: ! ~ & ^ | +
  • Max ops: 10
  • Rating: 1
    */

分析,解题过程和思路及学习

! 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假

逻辑运算值的确定 运算对象为非0表示逻辑值,值为1;运算对象为表示逻辑假,值为0。

内存中的数值为补码表示,所以0xFFFFFFFF是一个负数的补码。负数从补码求原码,最高符号位不变,保持 1, 其余各位求反,末尾加1,

代码

int isTmax(int x) {
  int neg1;
  neg1 = !(~x); // 如果x为-1, 则neg1为1,否则neg1为0,这里是为了排除-1的干扰
  return !((~(x+1)^x)|neg1); // 给x加1,再翻转,最后和自身取异或,如果x为Tmax,则返回1,否则返回0
}

x
01111111(127的原码) 10000001(-1的补码)
01111111(127的反码) 11111110(-1的反码)
01111111(127的补码) 11111111(-1的补码)
~x(内存中的数值为补码表示)
10000000 00000000
neg=!~x
00000000 00000001
x+1
11111111 00000000
~(x+1)
00000000 11111111
y=~(x+1)^x
10000000 00000000
y|neg
10000000 00000001

allOddBits

题目

  • /*
    • allOddBits - return 1 if all odd-numbered bits in word set to 1
    • where bits are numbered from 0 (least significant) to 31 (most significant)
    • Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
    • Legal ops: ! ~ & ^ | + << >>
    • Max ops: 12
    • Rating: 2
      */

分析,解题过程和思路及学习

a = 10101010 10101010 10101010 10101010 (0xAAAAAAAA)

a ^a =0

0xAAAAAAAA & 奇数位全为1的二进制数等于0xAAAAAAAA,其结果与0xAAAAAAAA异或为0。

0xAAAAAAAA & 奇数位不全为1的二进制数不等于0xAAAAAAAA,其结果与0xAAAAAAAA异或不为0。

代码

int allOddBits(int x) {
  int a = 0xAA | 0xAA << 8;
  a = a | a << 16;
  return !(a^(a&x));
}

negate

题目

/*

  • negate - return -x
  • Example: negate(1) = -1.
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 5
  • Rating: 2
    */

分析,解题过程和思路及学习

0(00000000)的负数为0(00000000)。

1(00000001)的负数为-1(10000001)。

负数的二进制一般通过正数反推导出,即(正数二进制 -> 取反 -> 补码(加1))

~x + x = -1,即~x+1=-x。

1(00000001)取反 = 11111110,+1 = 11111111(-1的补码)

代码

int negate(int x) {
  x = (~x) + 1;
  return x;
}

isAsciiDigit

题目

/*

  • isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters ‘0’ to ‘9’)
  • Example: isAsciiDigit(0x35) = 1.
  •        isAsciiDigit(0x3a) = 0.
    
  •        isAsciiDigit(0x05) = 0.
    
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 15
  • Rating: 3
    */

分析,解题过程和思路及学习

0x30(00110000)

0x39(00111001)

0x30 <= x <= 0x39,即x - 0x30 => 0且0x39 - x >= 0,即满足x的数符号位为0。

a - b可以看作 a + (-b),而 -b = ~x + 1。

代码

int isAsciiDigit(int x) {
  int a = x + (~(0x30) + 1);
  int b = 0x39 + (~x+1);
  a = a >> 31;
  b = b >> 31;
  return !(a | b);//保证条件同时满足
}

conditional

题目

/*

  • conditional - same as x ? y : z
  • Example: conditional(2,4,5) = 4
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 16
  • Rating: 3
    */

分析,解题过程和思路及学习

主要是实现三目运算。通过判断x,确定返回值,可以用!!x判断,!!x = 0 即 false 返回y,!!x = 1 即 true返回z。返回原值可以& -1实现,返回0可以用& 0实现。

代码

int conditional(int x, int y, int z) {
  int a = !!x;
  int b = ~a + 1;
  return (b & y) | (~b & z);
}

isLessOrEqual

题目

/*

  • isLessOrEqual - if x <= y then return 1, else return 0
  • Example: isLessOrEqual(4,5) = 1.
  • Legal ops: ! ~ & ^ | + << >>
  • Max ops: 24
  • Rating: 3
    */

分析,解题过程和思路及学习

y - x => 0, 即y + (~x+1) =>0。所得结果符号位为0。

代码

int isLessOrEqual(int x, int y) {
  int a = y + (~x + 1);
  int b = a >> 31;
  return !b;
}

logicalNeg

题目

/*

  • logicalNeg - implement the ! operator, using all of
  •          the legal operators except !
    
  • Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
  • Legal ops: ~ & ^ | + << >>
  • Max ops: 12
  • Rating: 4
    */

分析,解题过程和思路及学习

实现!运算。当x != 0时,返回0,当x = 0时,返回1。

一个非0数和其相反数异或后,结果的符号位为1。而0的相反数也为0,异或后符号位为0。

将二进制数向左移位操作,高位溢出则丢弃,低位补0

右移位运算中,无符号数和有符号数的运算并不相同。对于无符号数,右移之后高位补0;对于有符号数,符号位一起移动,正数高位补0,负数高位补1

代码

int logicalNeg(int x) {
  int a = x | (~x + 1);//符号位为1,即是有符号位负数
  int b = a >> 31;//b为0或-1
  return b+1;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值