c语言不使用加运算符做加法运算

本文深入探讨了CPU如何通过二进制运算执行加法,并提供了C语言的实现方式,包括使用位运算模拟加法过程,以及利用编译器特性间接实现加法运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我之前的博客里有讲到cpu是怎么做加减乘除的
偶然间看到一个面试题说的是不用加法去做加运算
其实仔细想想,就是以二进制的方式来运算咯,只不过把计算机组成原理里的那套搬到编程里来
复习一下加法:
在这里插入图片描述
cpu首先对加法的ADD指令是这样做的:
比如0001+0001
首先进行&运算等于0001+0001=0001 这里顺便复习一下与运算0&0=0,1&1=1,1&0或0&1=0
也就是说两数相等等于这个数,两数不相等等于0
进行与运算后,cpu有个进位条件,当两数为1时,就满足进位条件,所以需要做一个<<1的运算,除非两数为0则不做
这样就完成了一次运算,但是到这还没有结束
cpu还要检查一下其它的bit位有没有做完运算,所以cpu会把进位后的结果放到通用寄存器里存储着
如何判断其它bit位有没有做完运算?很简单,只需要进行一次xor运算就可以了
xor的运算是0任何数都等于任何数,而1任何数都等于任何数取反
cpu会将加数和被加数做一次xor运算,注意这里的加数与被加数不是进位后的数
0001^0001=0000
其结果会放在加数寄存器里
然后在把进位结果放到被加数寄存器里
那么此时加数寄存器=0000 而被加数寄存器=0010
cpu会判断一次被加数寄存器是否为0000如果不为0就代表还有位需要运算

那么cpu开始了第二次运算,重复上面的步骤
也就是 0000&0010
那么结果就是0000
如果是0000那么就不用进位了,直接进入下一个步骤
xor运算,注意结果被放入到了一个临时的通用寄存器里了,并不会放在加数与被加数的寄存器上,所以它们的值还是0000和0010
0000^0010=0010
这样看会更清晰吧:
0000
^^^^
0010
———
0010
0^任何数都等于任何数
然后在将结果放入到加法寄存器里,被加数寄存器里放入刚刚的临时通用寄存器里的结果0000
然后cpu判断被加数的bit位算完了就跳出循环
那么加法寄存器里就是答案
也成累加器寄存器
那么换算成c语言怎么换算呢?
1.函数:

int add(int a,int b);

a与b就是加数与被加数
这里我们直接使用,cpu的话会放入到累加器,这里我们省略一个变量
声明一个变量用来用临时的通用寄存器

int temp_reg = 0;

根据上面说的,是一个循环,每次循环判断被加数也就是b的进制位是否运算完,判断方法就是是否等于0,如果为0那么bit位都是0

while(b != 0){

}

根据上面说的,第一步做与运算然后把结果放入到临时寄存器里

temp_reg = a & b;

判断一下临时寄存器是否需要进位,上面说过进位的条件是bit位是否为0
如果每次&运算后bit位有一个不为0那么都需要进位一次

if(temp_reg != 0){
temp_reg = temp_reg << 1
}

然后根据上面说的做一次与运算,结果放入到加法寄存器里,这里你也可以在申请一个变量做累加器寄存器,这里我只是觉得这样写比较节省内存。因为cpu本身不是用加法寄存器保存这个数的,用的是累加器寄存器

a ^= b;

最后再把通用寄存器的结果放入到被加数寄存器里

b = temp_reg;

这样模拟cpu二进制加法运算的工作就完成了
最后一步直接return a即可
完整代码:

int add(int a, int b) {
unsigned int temp_reg=0;
while(b != 0){
temp_reg = a & b;
if(temp_reg != 0){
temp_reg=temp_reg<<1;
}
a ^= b;
b = temp_reg;
}
return a;
}

力扣:
在这里插入图片描述
还有一种写法
是利用编译器的解析器
但是这种方法是耍个小聪明原则上编译内部还是用了+符号
如,假设有一个char指针指向了一个包含’abcd’的字符串
char p;
那么p[2]编译器会翻译成
(p+2) 这个是指针的用法
是解引用,对这个地址取值,而&则是取这个地址
所以当我们用指针的方式来对变量进行运算:
int a,int b;
(char
)a[b]; 这样写可以让编译器帮我们隐式翻译成*(a+b)
那么问题是会对这块地址取值,解引用,但是这个地址是不安全的,因为这不是指针,实际地址就是a的值+b的值,但是这不是我们想要的,上面说了用&,只要在前面加一个&编译起会翻译成返回这块地址
也就是说把*(a+b)不对它解引用了,直接把它们当地址返回,就是返回a+b的值了
代码:
int add(int a,int b){

return (long)&(((char*)a)[b]);

}
注意返回的地址是指针,所以我们转换一下就可以了
这样的代码本质上还是使用了+

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

17岁boy想当攻城狮

感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值