直接上代碼
#include <stdio.h>
int add_one(int a, int b) {
return a - (-b);
}
int add_two(int a, int b) {
char *p = (char *) a;
int c = (int) &p[b];
return c;
}
int add_three(int a, int b) {
if (0 == b)
return a;
int cxor = a ^b;
int cand = a & b;
return add_three(cxor, cand << 1);
}
int add_four(int a, int b) {
int cxor = 0;
int cand = 0;
while (b != 0) {
cxor = a ^ b;
cand = (a & b) << 1;
a = cxor;
b = cand;
}
return cxor;
}
int main() {
printf("#########ONE#########\n");
int c = add_one(-20, -20);
printf("c = %d\n", c);
printf("#########TWO#########\n");
c = add_two(-30, -20);
printf("c = %d\n", c);
printf("#########THREE#########\n");
c = add_three(-40, 90);
printf("c = %d\n", c);
printf("#########FOUR#########\n");
c = add_four(40, -50);
printf("c = %d\n", c);
return 0;
}
輸出:
#########ONE#########
c = -40
#########TWO#########
c = -50
#########THREE#########
c = 50
#########FOUR#########
c = -10
add_one
int add_one(int a, int b) {
return a - (-b);
}
不解釋.......小聰明
add_two
int add_two(int a, int b) {
char *p = (char *) a;
int c = (int) &p[b];
return c;
}
使用p[b]
獲取char
數(shù)組 b個字節(jié)的偏移量.
int main() {
char a[10] = {'1','2','3','4','5'};
char *p = a;
printf("p = %p\n",p);
printf("a = %p\n",&a);
printf("a[2] = %c\n",a[2]);
printf("p+2= %c\n",*(p+2));
printf("a[2]的地址: ,%p\n",&a[2]);
printf("p + 2 的地址: %p\n",p+2);
}
輸出:
p = 0x7fff5ade795e
a = 0x7fff5ade795e
a[2] = 3
p+2= 3
a[2]的地址: ,0x7fff5ade7960
p + 2 的地址: 0x7fff5ade7960
指針 + 數(shù)字--> 指針類型指向的類型長度 * 數(shù)字 + 指針本來地址,現(xiàn)在把char 換為int
int a[10] = {'1', '2', '3', '4', '5'};
int *p = a;
printf("p = %p\n", p);
printf("a = %p\n", &a);
printf("a[2] = %d\n", a[2]);
printf("p+2= %d\n", *(p + 2));
printf("a[2]的地址: ,%p\n", &a[2]);
printf("p + 2 的地址: %p\n", p + 2);
輸出:
p = 0x7fff57360940
a = 0x7fff57360940
a[2] = 51
p+2= 51
a[2]的地址: ,0x7fff57360948
p + 2 的地址: 0x7fff57360948
add_three 和 add_four
int add_three(int a, int b) {
if (0 == b)
return a;
int cxor = a ^b;
int cand = a & b;
return add_three(cxor, cand << 1);
}
使用位運算來計算加法,涉及到位的操作.
^
異火運算符 簡稱不進位加法
0 ^ 0 = 0
1 ^ 0 = 1
1 ^ 1 = 0&
與運算符
0 ^ 0 = 0
1 ^ 0 = 0
1 ^ 1 = 1
使用^
運算符可以計算出兩個數(shù)相加的所有不進位的值
使用&
運算符可以計算出兩個數(shù)相加的所有進位值,
例如 :
- 計算 a = 11
b = 5
a + b = 16
a = 11 的二進制表示 1011
b = 5 的二進制表示 0101
cxor = a ^ b = 1 0 1 1
0 1 0 1
1 1 1 0
cand = a & b = 1 0 1 1
0 1 0 1
0 0 0 1
然后 cand << 1 = 0010,有進位,再次做運算
cxor = 1110 ^ 0010 = 1100
cand = 1110 & 0010 = 0010
cand << 1 = 0100, 有進位,再次做運算
cxor = 1100 ^ 0100 = 1000
cand = 1100 & 0100 = 0100
cand << 1 = 1000, 有進位,再次做運算
cxor = 1000 ^ 1000 = 0000
cand = 1000 ^ 1000 = 1000
cand << 1 = 0001 0000 有進位,再次做運算
cxor = 0000 0000 ^ 0001 0000 = 0001 0000
cand = 0000 0000 & 0001 0000 = 0000 0000
cand << 1 = 0 無進位,運算結(jié)束,相加值為 0001 000 = 16
我們計算一下負數(shù)的相加:
這里我們要清楚的是,所有的數(shù)值在計算機中存儲的都是補碼
將一個整數(shù)巾表,轉(zhuǎn)換成二進制,就是其原碼。如單字節(jié)的5的原碼為:0000 0101衰齐;-5的原碼為1000 0101已维。
反碼:正數(shù)的反碼就是其原碼啊终;負數(shù)的反碼是將原碼中部默,除符號位以外帽蝶,每一位取反绒怨。如單字節(jié)的5的反碼為:0000 0101纯赎;-5的反碼為1111 1010。
補碼:正數(shù)的補碼就是其原碼南蹂;負數(shù)的反碼+1就是補碼犬金。如單字節(jié)的5的補碼為:0000 0101;-5的原碼為1111 1011。
在計算機中晚顷,正數(shù)是直接用原碼表示的(正數(shù)的源碼= 反碼 = 補碼)峰伙,如單字節(jié)5,在計算機中就表示為:0000 0101音同。負數(shù)用補碼表示词爬,如單字節(jié)-5,在計算機中表示為1111 1011权均。
- 計算 a = - 11
b = 5
a + b = - 6
a = -11 在計算機中的二進制補碼表示 1111 0101
b = 5 的二進制表示 0000 0101
cxor = a ^ b = 1111 0101
0000 0101
1111 0000
cand = a & b = 1111 0101
0000 0101
0000 0101
然后 cand << 1 = 0000 1010 ,有進位,再次做運算
cxor = 1111 0000 ^ 0000 1010= 1111 1010
cand = 1111 0000 & 0000 1010 = 0000 0000
cand << 1 = 0 無進位,運算結(jié)束,相加值為 1111 1010 最高位為 1 說明是負數(shù),現(xiàn)在把補碼轉(zhuǎn)換為源碼:
先減1 ,然后除符號位外按位取反:
減 1 :
1111 1010 - 0000 0001 = 1111 1001
取反:
1111 1001 ---> 1000 0110
0110 = 6
最高位為 1 所以為 -6
總結(jié)
- 使用到了計算機中數(shù)值的表示,源碼,反碼,補碼 ,計算機中是用補碼來表示數(shù)值的
- 使用到地址的運算,與指針的運算
- 使用到
^
異或操作符 與&
與 操作符.