当前位置: 首页 > 知识库问答 >
问题:

这就是运算符在C中的实现方式吗?

锺英彦
2023-03-14

在了解如何在C中实现-*/等原始运算符时,我从一个有趣的答案中找到了以下片段。

// replaces the + operator
int add(int x, int y) {
    while(x) {
        int t = (x & y) <<1;
        y ^= x;
        x = t;
    }
    return y;
}

这个函数似乎演示了在后台的实际工作方式。然而,这对我来说太让人困惑了,无法理解。很长一段时间以来,我一直相信这样的操作是使用编译器生成的汇编指令来完成的!

运算符是否作为发布在MOST实现上的代码实现?这是否利用了两个的补充或其他与实现相关的特性?

共有3个答案

柳培
2023-03-14

似乎这个函数演示了如何在后台实际工作

不可以。这被转换为本机add机器指令,它实际上在ALU中使用硬件加法器。

如果你想知道计算机是如何添加的,这里有一个基本的加法器。

计算机中的一切都是用逻辑门完成的,逻辑门主要由晶体管构成。全加器中有半加器。

有关逻辑门和加法器的基本教程,请参见。这段视频非常有用,虽然很长。

在该视频中,显示了一个基本的半加法器。如果你想要一个简短的描述,就是它:

半加法器加上两位。可能的组合有:

  • 加0和0=0

那么半加法器是如何工作的呢?它由三个逻辑门组成,异或与非门。如果两个输入都为负,nand提供正电流,这意味着这解决了0和0的情况。异或给出一个正输出,一个输入为正,另一个为负,这意味着它解决了1和0的问题。只有当两个输入都为正时,才提供正输出,从而解决了1和1的问题。基本上,我们现在有了半加法器。但我们仍然只能添加一些。

现在我们制作全加法器。全加器由一次又一次地调用半加器组成。现在这有一个携带。当我们加1和1时,我们得到一个进位1。所以全加器所做的是,它从半加器获取进位,存储它,并将它作为另一个参数传递给半加器。

如果你不知道如何传递进位,你基本上先用半加法器把位相加,然后再把和和和进位相加。现在你已经添加了进位,两位。所以你一次又一次地这样做,直到你必须添加的部分结束,然后你得到你的结果。

惊讶吗?这就是它实际发生的方式。它看起来像一个漫长的过程,但计算机在几分之一纳秒内完成,或者更具体地说,在半个时钟周期内完成。有时甚至在一个时钟周期内执行。基本上,计算机有ALUCPU的主要部分)、内存、总线等。

如果你想学习计算机硬件,从逻辑门,内存和ALU,并模拟一台计算机,你可以看到这门课程,从中我学到了这一切:从第一原理构建一台现代计算机

如果你不想要电子证书,它是免费的。课程的第二部分将于今年Spring推出

凌翔宇
2023-03-14

当你加两位时,结果如下:(真值表)

a | b | sum (a^b) | carry bit (a&b) (goes to next)
--+---+-----------+--------------------------------
0 | 0 |    0      | 0
0 | 1 |    1      | 0
1 | 0 |    1      | 0
1 | 1 |    0      | 1

所以如果你按位异或,你可以得到不带进位的总和。如果你按位做,你可以得到进位位。

对多位数ab

a+b = sum_without_carry(a, b) + carry_bits(a, b) shifted by 1 bit left
    = a^b + ((a&b) << 1)

一旦b0

a+0 = a

所以算法可以归结为:

Add(a, b)
  if b == 0
    return a;
  else
    carry_bits = a & b;
    sum_bits = a ^ b;
    return Add(sum_bits, carry_bits << 1);

如果你摆脱递归,把它转换成循环

Add(a, b)
  while(b != 0) {
    carry_bits = a & b;
    sum_bits = a ^ b;

    a = sum_bits;
    b = carrry_bits << 1;  // In next loop, add carry bits to a
  }
  return a;

考虑到上述算法,来自代码的解释应该更简单:

int t = (x & y) << 1;

携带比特。如果两个操作数中右侧的1位均为1,则进位为1。

y ^= x;  // x is used now

不带进位的加法(忽略进位)

x = t;

重用x将其设置为携带

while(x)

当有更多进位时重复

递归实现(更容易理解)是:

int add(int x, int y) {
    return (y == 0) ? x : add(x ^ y, (x&y) << 1);
}

似乎这个函数演示了如何在后台实际工作

不。通常(几乎总是)整数加法转换为机器指令加法。这只是演示了一个使用按位异或和的替代实现。

鱼锦
2023-03-14

为了显得迂腐,C规范没有指定如何实现加法。

但实际上,小于或等于CPU字长的整数类型上的运算符会直接转换为CPU的加法指令,而较大的整数类型会转换为多个加法指令,并带有一些额外的位来处理溢出。

CPU内部使用逻辑电路来实现加法,不使用循环、位移位或任何与C的工作方式非常相似的东西。

 类似资料:
  • 本文向大家介绍c#中的三元运算符是?相关面试题,主要包含被问及c#中的三元运算符是?时的应答技巧和注意事项,需要的朋友参考一下 三元运算符,有的也称三目运算符,是对if else  双分支条件语句的简化 格式如下: 表达式一?表达式二:表达式三        释义:如果表达式一为真,就执行问号后边紧跟着的表达式,也就是表达式二;             否则执行冒号后边的表达式,即表达式三。 等价

  • 当我运行这段代码时,我得到以下错误截图 50:7:错误:与“操作员”不匹配

  • 问题内容: 我已经尝试实现sizeof运算符。 但是,对于任何一种数据类型,结果总是以“ 1”表示。 然后,我为此搜索了一下..,我发现代码是 强制转换的 如果代码是强制转换的,那么代码也可以正常工作。.我不明白为什么..该代码也完美地填充了结构。 它也为 有人能解释一下如果进行类型转换和未进行类型转换如何工作吗? 提前致谢.. 问题答案: 指针减法的结果以 元素 为单位,而不是以字节为单位。因此

  • 问题内容: 我正在尝试创建一个无符号整数类。 有没有办法实现诸如 +,-,*,/,<<,>>,|,^,>>>,<< 问题答案: Java不支持运算符重载。你是唯一的选择定义了类似的方法,,,等,并写出逻辑存在,并调用它们的特定操作。 您可以看一下BigInteger类,以了解如何定义支持各种操作的方法。如果有兴趣,您甚至可以浏览源代码,您可以在 jdk 主目录的 src 文件夹中找到该源代码。 _

  • 主要内容:算术运算符,关系运算符,逻辑运算符,位运算符,赋值运算符,其他运算符运算符其实就是一个符号,用来告诉编译器执行特定的数学或逻辑运算。C# 中内置了丰富的运算符,大致可以分为如下几类: 算术运算符; 关系运算符; 逻辑运算符; 位运算符; 赋值运算符; 其它运算符。 下面就来分别介绍一下这些运算符。 算术运算符 算术运算符即完成特定算术运算的符号,C# 中支持的算术运算符如下表所示:(假设变量 A = 10,变量 B = 20) 运算符 描述 实例 + 加法运算符,

  • 运算符是一个符号,告诉编译器执行特定的数学或逻辑操作。 C ++内置丰富的运算符,并提供以下类型的运算符 - 算术运算符 关系运算符 逻辑运算符 按位运算符 分配运算符 其它运算符 本章将逐一检查算术,关系,逻辑,按位,赋值和其他运算符。 算术运算符 (Arithmetic Operators) C ++语言支持以下算术运算符 - 假设变量A保持10,变量B保持20,则 - 显示示例 操作者 描述