0

I use the codeblock.

When the code is:

printf("%d",1/0);

The program can not run, there is an error. But when I write this:

printf("%d",1/0.0);

The program can run,and the output is 0. I want to know why.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
MAX
  • 11
  • 2
  • What none of these people are telling you below is that there are errors in floating point variables which are are **incredibly** small, and almost *never* zero, due to what's referred to as floating point error. That's *why* you get the value inf. It's the same as taking a limit of 1/x as x approaches 0. Your result approaches inifity. Integer division 1/0 is just 1/0 mathematically. – ciphermagi Dec 03 '13 at 03:37
  • 1
    0.0 is identically zero. And floating point division by zero *can* be an error if your floating point hardware is set up to raise it as one instead of just coming back with Inf. (At least, it can if it's 758). – hobbs Dec 03 '13 at 03:42
  • 1
    @JonahNelson: Floating-point rounding has nothing to do with the behavior at issue in this question. There is no error in converting the source text `0.0` to zero and no error in performing the division of 1 by 0 in a floating-point system that supports infinity; the result is “exactly” infinity with no rounding error. The reason for the observed output of “0” is that the OP is printing a `double` value with the wrong specifier, `%d`. – Eric Postpischil Dec 03 '13 at 14:18
  • @hobbs: It has nothing to do with hardware here. This case is subject to constant folding and any similar division will be substituted with constant that is result of such division at compile time. The problem here is that compiler compiles division by zero here when it shouldn't. If it would be 3.0/2.0 - for example - it will not be computed at runtime but compile time. – Artur Dec 04 '13 at 08:19

3 Answers3

5

1/0 or 1/0.0 are both undefined behavior:

C11 §6.5.5 Multiplicative operators

The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • 2
    Actually, I was going to go with one of the other answers on this one since I thought floating point 1/0 always gave infinity. But you're absolutely correct, it _is_ UB. Once that's the case, it doesn't really matter what format specifier you use, the damage is done :-) +1. I stand educated. – paxdiablo Dec 03 '13 at 03:37
  • @paxdiablo that is not totally true, since most platforms will support IEEE so it will most likely result in `inf` which will then go on to invoke undefined behavior due to the wrong format specifier, so they both matter. Undefined does not mean the implementation can not define it you just need to understand your implementation. I just wish I could find a nice IEEE reference that is easily sharable. – Shafik Yaghmour Dec 03 '13 at 04:44
  • Shafik, actually undefined means you cant rely on it regardless of what the implentation states. You may complain that an implementation is buggy if it states it returns inf then doesn't but that's still conformant with the standard. The other lesser areas (implementation defined, locale specific and so on) are less problematic. – paxdiablo Dec 03 '13 at 06:05
  • @paxdiablo one of the more well known cases would be type punning which is undefined in many cases but most compilers I know of document that it is supported in those undefined areas. It is obviously still undefined as per the standard but well defined with respect to a specific compiler and the compilers writers have little reason to just randomly break features they clearly document is valid. – Shafik Yaghmour Dec 03 '13 at 10:26
  • 1
    @paxdiablo: When behavior is undefined by the C standard, that just means the C standard imposes no requirements on the behavior. It does not mean you cannot rely on behavior specified by an implementation. The C standard does not define its use of “undefined” to override implementation specifications. In fact, the C standard is designed to be extendable by implementations. Essentially every practical program that does something other than pure computation uses behavior beyond the C standard (e.g., behavior provided by vendor libraries). – Eric Postpischil Dec 03 '13 at 12:20
  • Eric, perhaps I didn't make myself clear. You're correct, the standard simply states that UB is "behavior ... for which this International Standard imposes no requirements". What I meant is that, even if the implementation violates its own doco for UB, that in no way makes it a non-conformant compiler in respect to the standard. The standard says nothing about UB being okay if the implementation specifies it. The _implementation_ may guarantee certain behaviour but that's nothing to do with the standard. – paxdiablo Dec 03 '13 at 12:46
  • For maximum portability, I generally avoid UB altogether and ensure implementation specified behaviour is split out into separate areas so they can just be replaced easily when moving to a different implementation. If you don't value (or need) portability, it's okay to use ISB or even UB if the implementation guarantees it will always follow the same rules). But I see where you're all coming from, I think it was just a miscommunication on my part. – paxdiablo Dec 03 '13 at 12:48
  • 1
    @paxdiablo: There is no reason to believe that, in the behavior observed in regard to this question, a C implementation is violating its own documentation. The behavior reported by the OP is fully explained by the fact that `%d` is incorrectly used to print a `double`. It is almost certainly not caused by dividing by zero in floating-point. – Eric Postpischil Dec 03 '13 at 14:21
2

You are invoking undefined behavior of two different forms one by dividing by zero, the draft standard section 6.5.5 Multiplicative operators paragraph 5 says (emphasis mine):

The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder. In both operations, if the value of the second operand is zero, the behavior is undefined.

The second by using the wrong format specifier in printf, you should be using %f since the result of 1/0.0 is a double not an int. The C99 draft standard section 7.19.6.1 The fprintf function which also covers pritnf in paragraph 9 says:

If a conversion specification is invalid, the behavior is undefined.248) If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

Although if the implementation supports IEEE 754 floating point division by zero should result in either +/- inf. and 0/0.0 will produce a NaN. Important to note that relying on __STDC_IEC_559__ being defined may not work as I note in this comment.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
0

In theory, the result of 1/0.0 may be undefined in a C implementation, since it is undefined by the C standard. However, in the C implementation you use, the result is likely infinity. This is because most common C implementations use (largely) IEEE 754 for floating-point operations.

In this case, the cause of the output you see is that 1/0.0 has double type, but you are printing it with %d, which requires int type. You should print it with a specifier that accepts the double type, such as %g.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312