两种解法:
法一:
int aplusb(int a, int b) { char* c = (char *)a; return (int)&c[b]; }
解释:
举例a=2, b=3;
1.先将a的值2转化成为一个指向字符型的指针c(值为0x00000002)
2.利用数组地址是相加的原理,将c的这个地址值再加上一个b,此时c[b]返回的应该是c+b地址中存的char值,然而我们要的是c+b的地址:0x00000005,所以再取地址。然后强转int后返回。
疑惑问题分析:用char* 而不用int*?
因为char类型在C语言中是一个字节的!而int是4字节,如果char* 变量+ 1 变量前进一个字节。而若是int* c 的话,c[b]返回的就是c + b*4处的地址值。
法二:
int aplusb(int a, int b){ int sum; //和 int carry; //进位 while(b != 0){ sum = a^b; carry = (a&b)<<1; a = sum; b = carry; } return a; }
解释:
(1)异或运算:
异或运算一共三种可能:
0 ^0 = 0
0^1 = 1
1^1 = 0
我们发现它刚好符合某单一位的加法的运算规则(在不考虑进位的情况下)
剩下的进位问题怎么办呢?
(2)与运算:
与运算只有在两个位都是1的情况下结果才是1。这符合进位的运算规则。所以我们用它来解决我们上面遇到的进位问题。
以7(0111)+3(0011) = 10(1010)为例:
从上面可以看到第一次相与后的结果应该是第一次进位0110,
为什么能同时计算出两位的进位呢?
这就是与运算的便捷,能及时看出其中“当前要进的位”,而不管有几位。而所谓“明显”就是进位后不知道更高位是否还需进一步进位,但是此刻满足两个1相与必须要进的位。
这也是为什么要将(进位)和(不进位时的和)分别求出来后还要进入下一次循环的原因——因为不知道加上进位后,是否更高一位还需要进一步进位。
问题:将b左移行不行?
答:不行,因为这是进位,需要将进位向左边移动,如果右移则将进位丢掉了。