-2

I've been playing around with bitwise operations and two's complement, when I discovered this oddity.

#include <stdio.h>
int main ()
{
    int tmin = 0x80000000;
    printf("tmin + tmin: 0x%x\n", tmin + tmin);
    printf("!(tmin + tmin): 0x%x\n", !(tmin + tmin));
}

The code above results in the following output

tmin + tmin: 0x0
!(tmin + tmin): 0x0

Why does this happen?

Rushabh Mehta
  • 1,529
  • 1
  • 13
  • 29
  • 7
    You're overflowing, so it causes undefined behavior. Use `unsigned int`. – Barmar Oct 09 '19 at 23:31
  • You're missing a `)` on the second `printf` line. – Barmar Oct 09 '19 at 23:32
  • @MooingDuck I'm aware of overflow, I'm just confused because the output of the first printf seems to suggest that tmin + tmin is 0, but apparently it is not? – Rushabh Mehta Oct 09 '19 at 23:34
  • 4
    @DonThousand: The program has undefined behavior, so anything can happen. – R.. GitHub STOP HELPING ICE Oct 09 '19 at 23:40
  • 1
    The C standard does not say there is one specific result of an overflow in the `int` type. It says, anytime there is an `int` overflow, the C implementation can do anything it wants, and it can be different each time. As others have indicated but not explained, this is called undefined behavior, meaning the C standard does not impose any requirements at all. In the cases you ask about, the C compiler may simply be doing what is “easiest” for it. For example, the compiler could take an entire expression containing overflow and reduce it to 0, regardless of what else it contains. – Eric Postpischil Oct 10 '19 at 02:52
  • Or it could remove the expression evaluation completely and let whatever happens to be in a processor register at that point be the result. – Eric Postpischil Oct 10 '19 at 02:54

1 Answers1

2

0x80000000 in binary is

0b10000000000000000000000000000000

When you add two 0x80000000s together,

    |<-          32bits          ->|
  0b10000000000000000000000000000000
+ 0b10000000000000000000000000000000
------------------------------------
 0b100000000000000000000000000000000
    |<-          32bits          ->|

However, int on your machine seem to have 32 bits, so only the lower 32 bits are preserved, which means the 1 in your result is silently discarded. This is called an Integer Overflow.

Also note that in C, signed (as opposed to unsigned, i.e. unsigned int) integer overflow is actually undefined behavior, which is why !(tmin + tmin) gives 0x0 instead of 0x1. See this blog post for an example where a variable is both true and false due to another undefined behavior, i.e. uninitialized variable.

nalzok
  • 14,965
  • 21
  • 72
  • 139
  • 2
    This doesn't explain the second case. – S.S. Anne Oct 09 '19 at 23:55
  • I think I figured out my point of confusion now. If I cast the sum of tmin + tmin to an int, and then call !sum, then it will return 1 as expected. – Rushabh Mehta Oct 09 '19 at 23:59
  • 2
    @DonThousand "If I cast the sum of tmin + tmin to an int, and then call !sum, then it will return 1 as expected." --> You are still missing the point. The result is not _expected_, but _undefined behavior_. – chux - Reinstate Monica Oct 10 '19 at 01:37
  • @JL2210 It does, as undefined behavior can explain anything. Edited to clarify. – nalzok Oct 10 '19 at 02:57
  • @DonThousand In case you don't know what is being hinted at by "undefined behavior" it's basically that corner of the specification where they didn't demand a particular outcome. So, if you have an operation that falls into undefined behavior; even if the answer _should_ be zero according to the laws of mathematics, the answer you get _might_ be zero, or one, or a million, random, or any other number you can think of, as it's subject to the computer it's running on, and whatever implementation is taking hold at the moment. "Undefined behavior" == "all bets are off, logic does not apply". – Edwin Buck Oct 10 '19 at 04:10
  • @EdwinBuck Yes I understand. It was just an observation. – Rushabh Mehta Oct 10 '19 at 04:40
  • @DonThousand I'm glad you do. Sorry if I explained it unnecessarily. – Edwin Buck Oct 10 '19 at 04:50