【发布时间】:2010-08-15 16:05:22
【问题描述】:
我已经用 C++ 编程了一段时间,但突然有了疑问,想向 Stackoverflow 社区澄清一下。
当一个整数除以另一个整数时,我们都知道结果是一个整数,同样,一个浮点数除以一个浮点数也是一个浮点数。
但是谁负责提供这个结果呢?是编译器还是DIV指令?
【问题讨论】:
-
你是在划分常量还是变量?
标签: c++ c integer division integer-division
我已经用 C++ 编程了一段时间,但突然有了疑问,想向 Stackoverflow 社区澄清一下。
当一个整数除以另一个整数时,我们都知道结果是一个整数,同样,一个浮点数除以一个浮点数也是一个浮点数。
但是谁负责提供这个结果呢?是编译器还是DIV指令?
【问题讨论】:
标签: c++ c integer division integer-division
这取决于您的架构是否具有 DIV 指令。如果您的体系结构同时具有整数和浮点除法指令,编译器将针对代码指定的情况发出正确的指令。语言标准规定了类型提升的规则,以及在每种可能的情况下应该使用整数除法还是浮点除法。
如果您只有一个整数除法指令,或者只有一个浮点除法指令,编译器将内联一些代码或生成对数学支持库的调用来处理除法。除法指令是出了名的慢,所以大多数编译器会尽可能地优化它们(例如,用移位指令替换,或预先计算编译时常量除法的结果)。
【讨论】:
编译器将在编译时根据所使用的变量类型决定需要哪种形式的除法 - 最终会涉及到一种或另一种形式的 DIV(或 FDIV)指令。
【讨论】:
float x = 1.0/3.0 可能由编译器评估,也可能导致 FDIV - 编译器的选择。
硬件除法指令几乎从不包括整数和浮点数之间的转换。如果你得到了除法指令(它们有时会被忽略,因为除法电路又大又复杂),它们实际上肯定是“将 int 除以 int,产生 int”和“将 float 除以 float,产生 float” .而且通常输入和输出的大小也是一样的。
编译器负责在这些原语之上构建源代码中编写的任何操作。例如,在 C 语言中,如果将浮点数除以 int,编译器将发出 int-to-float 转换,然后是浮点数。
(确实存在古怪的例外情况。我不知道,但我不会把它放在 VAX 之外,因为它有“将浮点数除以 int”类型的指令。Itanium 并没有真正的除法指令,但它的“除法助手”仅用于浮点,您必须在浮点除法之上伪造整数除法!)
【讨论】:
你的问题真的没有意义。 DIV 指令本身不会做任何事情。不管你对它大声喊叫,即使你试图贿赂它,它也不会对任何事情负责
当您使用编程语言 [X] 进行编程时,[X] 编译器的唯一责任是制作一个执行您在源代码中描述的程序。
如果请求除法,编译器将决定如何进行除法。这可能通过为DIV 指令生成操作码来实现,如果您的目标 CPU 有一个。它可能是通过在编译时预先计算除法,然后将结果直接插入程序中(假设两个操作数在编译时已知),或者它可能通过生成一起模拟的指令序列来完成 一个部门。
但它总是取决于编译器。除非根据 C++ 标准进行解释,否则您的 C++ 程序不会有任何 效果。如果您将其解释为纯文本文件,则它不会执行任何操作。如果您的编译器将其解释为 Java 程序,它将阻塞并拒绝它。
而且 DIV 指令对 C++ 标准一无所知。另一方面,C++ 编译器编写的唯一目的是理解 C++ 标准,并根据它转换代码。
编译器始终负责。
【讨论】:
C++ 标准中最重要的规则之一是“好像”规则:
本国际标准中的语义描述定义了一个参数化的非确定性抽象机器。本国际标准对一致性实现的结构没有要求。特别是,它们不需要复制或模仿抽象机器的结构。相反,需要符合要求的实现来模拟(仅)抽象机的可观察行为,如下所述。
这与您的问题有关,这意味着只要完成,划分哪个组件并不重要。它可以由DIV 机器代码执行,如果没有针对相关处理器的适当指令,它可以由更复杂的代码执行。
它还可以:
【讨论】:
if(true == false) 之类的操作来欺骗编译器让您编译)。编译器产生非标准化警告肯定是合理且有用的。
x * 0.4替换x/2.5。这实际上很常见,因为乘法通常比除法更快。
C99 标准定义“当整数被除时,/ 运算符的结果 是任何小数部分的代数商 丢弃。”并在脚注中补充说“这通常被称为'向零截断'。”
从历史上看,语言规范负责。
Pascal defines its operators 这样使用/ 进行除法总是返回real(即使您使用它来除2 个整数),如果您想将整数除以得到整数结果,则使用@改为 987654324@ 运算符。 (Visual Basic 也有类似的区别,它使用\ 运算符进行整数除法,返回整数结果。)
在 C 中,如果您想要浮点结果,则决定应该通过将整数操作数之一转换为 float 来进行相同的区分。以您在许多 C 派生语言中描述的方式处理整数与浮点类型已成为惯例。我怀疑这个约定可能起源于 Fortran。
【讨论】: