views:

236

answers:

6

I've been programming for a while in C++, but suddenly had a doubt and wanted to clarify with the Stackoverflow community.

When an integer is divided by another integer, we all know the result is an integer and like wise, a float divided by float is also a float.

But who is responsible for providing this result? Is it the compiler or DIV instruction?

+11  A: 

That depends on whether or not your architecture has a DIV instruction. If your architecture has both integer and floating-point divide instructions, the compiler will emit the right instruction for the case specified by the code. The language standard specifies the rules for type promotion and whether integer or floating-point division should be used in each possible situation.

If you have only an integer divide instruction, or only a floating-point divide instruction, the compiler will inline some code or generate a call to a math support library to handle the division. Divide instructions are notoriously slow, so most compilers will try to optimize them out if at all possible (eg, replace with shift instructions, or precalculate the result for a division of compile-time constants).

Carl Norum
+3  A: 

The compiler will decide at compile time what form of division is required based on the types of the variables being used - at the end of the day a DIV (or FDIV) instruction of one form or another will get involved.

Will A
Unless the variables are compile-time constants, in which case the compiler will "take responsibility" and no instructions are produced.
Potatoswatter
@Potatoswatter: Not entirely true; the compiler MUST evaluate Integral Constant Expressions and MAY evaluate other constant expressions. I.e. `float x = 1.0/3.0` may be evaluated by the compiler, or it may result in an FDIV - compiler's choice.
MSalters
+2  A: 

Hardware divide instructions almost never include conversion between integer and floating point. If you get divide instructions at all (they are sometimes left out, because a divide circuit is large and complicated), they're practically certain to be "divide int by int, produce int" and "divide float by float, produce float". And it'll usually be that both inputs and the output are all the same size, too.

The compiler is responsible for building whatever operation was written in the source code, on top of these primitives. For instance, in C, if you divide a float by an int, the compiler will emit an int-to-float conversion and then a float divide.

(Wacky exceptions do exist. I don't know, but I wouldn't put it past the VAX to have had "divide float by int" type instructions. The Itanium didn't really have a divide instruction, but its "divide helper" was only for floating point, you had to fake integer divide on top of float divide!)

Zack
Heh. As for the "wacky exceptions", as you call them, you probably used one just now to write this answer. The x86 (or more precisely x87) instruction for *divide float by int* is called FIDIV.
slacker
And it is not the only point where the wackiness of x86 puts VAX to shame :).
slacker
Hah! Well, it would be the x87. They didn't do _anything_ the normal way with that thing.
Zack
A: 

Practically

The C99 standard defines "When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded." And adds in a footnote that "this is often called 'truncation toward zero.'"

History

Historically, the language specification is responsible.

Pascal defines its operators so that using / for division always returns a real (even if you use it to divide 2 integers), and if you want to divide integers and get an integer result, you use the div operator instead. (Visual Basic has a similar distinction and uses the \ operator for integer division that returns an integer result.)

In C, it was decided that the same distinction should be made by casting one of the integer operands to a float if you wanted a floating point result. It's become convention to treat integer versus floating point types the way you describe in many C-derived languages. I suspect this convention may have originated in Fortran.

Ken Bloom
+1  A: 

One of the most important rules in the C++ standard is the "as if" rule:

The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below.

Which in relation to your question means it doesn't matter what component does the division, as long as it gets done. It may be performed by a DIV machine code, it may be performed by more complicated code if there isn't an appropriate instruction for the processor in question.

It can also:

  1. Replace the operation with a bit-shift operation if appropriate and likely to be faster.
  2. Replace the operation with a literal if computable at compile-time or an assignment if e.g. when processing x / y it can be shown at compile time that y will always be 1.
  3. Replace the operation with an exception throw if it can be shown at compile time that it will always be an integer division by zero.
Jon Hanna
@Jon Hanna: Could it refuse to compile if it could deduce at compile time that the quotient would always be zero, or is it legitimate for a fully-conforming C program to contain an instruction like x=1/(x-x); provided such an instruction never actually executes?
supercat
@supercat:It is perfectly legitimate. It is the *execution* of a division by zero which causes undefined behavior.
slacker
@supercat if you want to produce a program that always errors, that's your business! It's hard after all to teach people about errors without them (though in some languages you have to do stuff like `if(true == false)` to trick compilers into letting you compile). It would certainly be reasonable, and useful, for the compiler to produce a non-standardised warning.
Jon Hanna
... the important thing is that if an infallible expert on the language says "it will behave thus" then it must do what the expert says as seen from the outside. How it does it is up to the compiler. Those bits that are "undefined" are where the expert will say "I don't know what it will do" (actually he'll probably rant about bad code, you know what experts are like), but defined only applies to "outside" views. This is important in allowing for optimisations, and indeed much of the STL depends on this to not really suck in performance terms.
Jon Hanna
The compiler may also replace `x/2.5` with `x * 0.4`. This is in fact common as multiplication is often faster than division.
MSalters
+1  A: 

Your question doesn't really make sense. The DIV instruction doesn't do anything by itself. No matter how loud you shout at it, even if you try to bribe it, it doesn't take responsibility for anything

When you program in a programming language [X], it is the sole responsibility of the [X] compiler to make a program that does what you described in the source code.

If a division is requested, the compiler decides how to make a division happen. That might happen by generating the opcode for the DIV instruction, if the CPU you're targeting has one. It might be by precomputing the division at compile-time, and just inserting the result directly into the program (assuming both operands are known at compile-time), or it might be done by generating a sequence of instructions which together emulate a divison.

But it is always up to the compiler. Your C++ program doesn't have any effect unless it is interpreted according to the C++ standard. If you interpret it as a plain text file, it doesn't do anything. If your compiler interprets it as a Java program, it is going to choke and reject it.

And the DIV instruction doesn't know anything about the C++ standard. A C++ compiler, on the other hand, is written with the sole purpose of understanding the C++ standard, and transforming code according to it.

The compiler is always responsible.

jalf