7

我已经用 C++ 编程了一段时间,但突然有疑问并想与 Stackoverflow 社区澄清一下。

当一个整数除以另一个整数时,我们都知道结果是一个整数,同样,一个浮点数除以一个浮点数也是一个浮点数。

但是谁负责提供这个结果呢?是编译器还是 DIV 指令?

4

6 回答 6

12

这取决于你的架构是否DIV指令。如果您的架构同时具有整数和浮点除法指令,编译器将针对代码指定的情况发出正确的指令。语言标准规定了类型提升的规则,以及在每种可能的情况下应该使用整数除法还是浮点除法。

如果您只有一个整数除法指令,或者只有一个浮点除法指令,编译器将内联一些代码或生成对数学支持库的调用来处理除法。除法指令是出了名的慢,所以大多数编译器会尽可能地优化它们(例如,用移位指令替换,或者预先计算编译时常量除法的结果)。

于 2010-08-15T16:08:25.243 回答
3

编译器将在编译时根据所使用的变量的类型决定需要哪种形式的除法 - 最终将涉及一种或另一种形式的 DIV(或 FDIV)指令。

于 2010-08-15T16:09:01.377 回答
3

硬件除法指令几乎从不包括整数和浮点之间的转换。如果你得到了除法指令(它们有时会被忽略,因为除法电路又大又复杂),它们实际上肯定是“将 int 除以 int,产生 int”和“将 float 除以 float,产生 float” . 而且通常输入和输出的大小也都相同。

编译器负责在这些原语之上构建源代码中编写的任何操作。例如,在 C 中,如果将浮点数除以整数,编译器将发出整数到浮点数的转换,然后是浮点数除法。

(确实存在古怪的例外。我不知道,但我不会把它放在 VAX 之外,因为它有“将浮点数除以 int”类型的指令。安腾并没有真正的除法指令,但它的“除法助手” "适用于浮点数,您必须在浮点除法之上伪造整数除法!)

于 2010-08-15T16:47:21.577 回答
2

你的问题真的没有意义。DIV 指令本身不执行任何操作。无论你对它大声喊叫,即使你试图贿赂它,它也不承担任何责任

当您使用编程语言 [X] 进行编程时,[X] 编译器的唯一责任是制作一个执行您在源代码中描述的程序

如果请求除法,编译器将决定如何进行除法。DIV如果您的目标 CPU 有一个,那么这可能会通过为指令生成操作码来实现。它可能是通过在编译时预先计算除法,并将结果直接插入程序中(假设两个操作数在编译时都是已知的),或者它可以通过生成一系列指令来共同模拟除法。

但这始终取决于编译器。除非根据 C++ 标准进行解释,否则您的 C++ 程序不会产生任何影响。如果您将其解释为纯文本文件,它不会做任何事情。如果您的编译器将其解释为 Java 程序,它将阻塞并拒绝它。

而且 DIV 指令对 C++ 标准一无所知。另一方面,编写C++ 编译器的唯一目的是理解 C++ 标准,并根据它转换代码。

编译器始终负责。

于 2010-08-15T18:47:46.330 回答
1

C++ 标准中最重要的规则之一是“好像”规则:

本国际标准中的语义描述定义了一个参数化的非确定性抽象机。本国际标准对一致性实现的结构没有要求。特别是,它们不需要复制或模仿抽象机器的结构。相反,需要符合要求的实现来模拟(仅)抽象机的可观察行为,如下所述。

这与您的问题有关,这意味着只要完成,划分哪个组件并不重要。它可以由DIV机器代码执行,如果没有针对相关处理器的适当指令,它可以由更复杂的代码执行。

它还可以:

  1. 如果合适并且可能更快,则将操作替换为位移操作。
  2. 如果在编译时可计算,则将操作替换为文字,或者如果在处理 x / y 时可以在编译时显示 y 将始终为 1,则将其替换为赋值。
  3. 如果可以在编译时显示它始终是整数除以零,则将操作替换为异常抛出。
于 2010-08-15T17:25:19.100 回答
0

几乎

C99 标准定义“当整数被除法时,/ 运算符的结果是代数商,其中任何小数部分被丢弃。” 并在脚注中补充说,“这通常被称为‘向零截断’。”

历史

从历史上看,语言规范是负责任的。

Pascal定义了它的运算符,以便使用/for 除法总是返回 a real(即使你用它来除 2 个整数),如果你想将整数相除并得到一个整数结果,你可以使用div运算符来代替。(Visual Basic 也有类似的区别,它使用\返回整数结果的整数除法运算符。)

float在 C 中,如果您想要浮点结果,则决定通过将整数操作数之一转换为 a 来进行相同的区分。以您在许多 C 派生语言中描述的方式处理整数与浮点类型已成为惯例。我怀疑这个约定可能起源于 Fortran。

于 2010-08-15T17:05:10.013 回答