0

A c programming book that I'm reading(c programming, a modern approach 2nd edition) says that when an "overflow occurs during an operation on unsigned integers, though, the result is defined."

Here is a small code example

#include <stdio.h>

int main()
{
  unsigned short int x = 65535; // The unsigned short int is at the maximum possible range
  x += 1; // If I add one to it will overflow.
  printf("%u", x); // the output will be zero or one if decide to add plus one again to x
  return 0;
}

He then goes to say that "for signed integers, the behaviors for these integers are not defined". Meaning the program can either print out the incorrect result or it can crash the program.

Why is this so?

5
  • 1
    Are you asking why the behaviour of signed integer overflow is undefined, (because the language specification says it is), or why the specification defines unsigned integer overflow but declares signed integer overflow to be undefined (different representations of signed values)? Also, please don't print unsigned values with %d - %u exists for a reason. Commented May 8, 2015 at 22:34
  • @IskarJarak "why the specification defines unsigned integer overflow but declares signed integer overflow to be undefined?" This part of your sentence is what I'm asking. Commented May 8, 2015 at 22:38
  • @LuisAverhoff See the duplicate link then. This has been asked before. Commented May 8, 2015 at 22:38
  • @IskarJarak Alright, I also changed it to %u instead of %d. Commented May 8, 2015 at 22:39
  • @LuisAverhoff Great. Since you're printing an unsigned short, you could also consider %hu instead, although %u should work fine anyway. Commented May 8, 2015 at 22:41

1 Answer 1

3

It comes down to hardware representation, and there being more than one way to represent signed integral types in binary (sign magnitude, ones complement, twos complement) and operations on them. Those have quite different implications when an overflow occurs (e.g. triggering a hardware trap, working with modulo, etc).

All of the obvious means of representing unsigned integral values in binary and implementing numerical operations on such values have the same consequence - essentially that numeric operations in hardware work with a modulo arithmetic.

For basic types (and other things) the standard generally allows freedom to compiler vendors when there is more than one feasible way of implementing something, and those options have different consequences. There are multiple ways with signed integral types, and real-world hardware that uses each approach. They are different enough to warrant the behaviour being undefined (as that term is defined in the standard).

Sign up to request clarification or add additional context in comments.

4 Comments

This answer is totally correct. It is also worth mentioning that, unfortunately, because the standard says the behavior is undefined, that leaves compiler vendors open to do anything. Overflowing a signed int via addition in C doesn't necessarily have to do what your CPU's ADD instruction does on overflow. Optimizers have been known to exploit this undefinedness and optimize away the addition entirely. IMO this is a dangerous game to be playing with the spec.
True. I'll think about it, but my first thought is that this is going a bit far afield given the original question. What you describe is the sort of self-fulfilling prophecy sometimes associated with undefined behaviour (something is undefined in standard because of an existing range of real-world behaviours then, because it is undefined, implementers choose to support even more possible behaviours). However, that is a consequence of something being undefined, not the reason it was left undefined in the first place.
Well, for me, the obvious inference from "it's undefined because different CPUs have different behaviors" is that "the C compiler will follow the behavior of my CPU architecture", but the reality is far more subtle. It's a trap.
@StilesCrisis: it's only a trap because the authors of some compilers failed to recognize that (as documented in the C99 Rationale), the authors of the Standard viewed the question of how to process many useful but non-portable constructs for which the Standard imposes no requirements as a "Quality of Implementation" issue outside the Standard's jurisdiction. They failed to recognize that a compiler that's freely distributable need not be very good to stomp others in the marketplace that would in every other way better fit their customers' needs.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.