18

I'm having trouble understanding, what were the exact purposes of creating the short, int, and long data types in C?

The reason I ask is, it doesn't seem like their sizes are bounded -- they could be of any size, so long as short is smaller than an int, for example.

In which situations, then, should you use an unsigned int or unsigned long, for example, instead of a size_t, when doing so offers no hope of binary compatibility?

(If you don't know the size, then how would you know when to choose which?)

8
  • 2
    Check out <stdint.h>
    – BlackJack
    Commented Oct 20, 2011 at 2:25
  • 1
    @BlackJack: Haha yes I actually have -- but I guess my question is, why aren't all those types defined natively instead? Is it a "hindsight is 20/20" issue, or was there a specific reason?
    – user541686
    Commented Oct 20, 2011 at 3:08
  • 2
    C was meant to be both portable and close to the underlying hardware. There were platforms where byte was not 8 bit long - but you still could use C. No fixed set of data types would ever be sufficient, no fixed size integere could ever be portable.
    – SK-logic
    Commented Oct 20, 2011 at 15:01
  • @SK-logic: Not even if they said sizeof(short) == 2 * sizeof(char) or similar?
    – user541686
    Commented Oct 20, 2011 at 17:39
  • 1
    There are platforms where sizeof(char) == sizeof(short), and it makes sense. Unfortunately, there is no way to specify integral number types that way that they'll fit all the possible and existing platforms.
    – SK-logic
    Commented Oct 20, 2011 at 18:28

4 Answers 4

13

It'd be defined by the architecture you were using. On a Zilog z80 chip (common embedded chip) they'd be one size while they could be an entirely different size on a x86 chipset. However, the sizes themselves are fixed ratios to each other. Essentially short and long aren't types but qualifies for the int type. Short ints will be one order of magnitude smaller than (regular) int and long ints will be an order of magnitude higher. So say your Int is bounded to 4 bytes, the short qualifier bounds it to 4 bytes though 2 bytes is also very common and the long qualifier boosts it potentially to 8 bytes though it can be less down to 4 bytes. Keep in mind that this is subject to word length as well so on a 32 bit system you'd max out at 4 bytes per int anyway making long the same as a regular int. Thus, Short ≤ Int ≤ Long.

However, if you lengthen it again, you can push in the int to the next cell giving you 8 whole bytes of storage. This is the word size for 64 bit machines so they don't have to worry about such things and just use the one cell for long ints allowing them to be another order above standard ints while long long ints get really bit.

As far as which to choose, it boils down to something that Java programmers for instance don't have to worry about. "What is your architecture?" Since it all depends on the word size of the memory of the machine in question, you have to understand that up front before you decide which to use. You then pick the smallest reasonable size to save as much memory as you can because that memory will be allocated whether you use all of the bits in it or not. So you save where you can and pick shorts when you can and ints when you can't and if you need something bigger than what regular ints you give; you'd lengthen as needed until you hit the word ceiling. Then you'd need to supply big number routines or get them from a library.

C may well be "portable assembly" but you still have to know thine hardware.

4
  • 11
    this is not quite right, shorts do not have to be smaller than ints, they can't be bigger than ints
    – jk.
    Commented Oct 20, 2011 at 10:16
  • I'll correct that.
    – user28988
    Commented Oct 20, 2011 at 14:38
  • 2
    Similarly, longs can't be smaller than ints. Commented Oct 20, 2011 at 15:14
  • 1
    indeed I believe there have been machines where short, int and long where exactly the same.
    – jk.
    Commented Nov 3, 2011 at 10:48
6

Although today, a "byte" means "8 bits", that hasn't always been true. Machines have used addressable chunks of 4 bits, 8 bits, 12 bits, 16 bits, 32 bits, and 36 bits (and probably some other sizes as well). One of the design intentions of C was to be usable on machines with different memory sizes and configurations.

I think the design intention was originally that each type other than int be the smallest thing that could handle numbers of various sizes, and that int be the most practical "general-purpose" size that could handle +/-32767. I don't think there was any desire or intention to create a language which would still be in use when computers became so powerful that operations on 64-bit numbers cost the same as operations on smaller ones.

The biggest problem with C's integer-type semantics is that in some contexts they represent cardinal numbers or mathematical integers, while in other contexts they're used to represent members of a wrapping abstract algebraic ring of integers congruent mod 2^n [so e.g. subtracting the maximum representable value from 0 is defined to yield 1], but the behaviors are specified more on the basis of what compilers seemed to do the days when computer word sizes were around 16 bits (and a 36-bit word size would have been huge), rather than on the basis of what would make sense on a 64-bit machine. Consequently, the result of subtracting a 32-bit unsigned value from a smaller unsigned 32-bit value may either be a large 32-bit unsigned value, or a negative 64-bit number.

4

https://stackoverflow.com/questions/589575/size-of-int-long-etc

So in the most commonly used architectures, char is 1 byte, short and int are at least 2 bytes, and long is at least 4 bytes.

And it's intended that 'int' should be the most natural/normal/efficient representation for the current CPU.

So the general rule is to use 'int' unless your values exceed +/-32K, making you (on older CPUs) use 'long'. ...or unless you're making big arrays of small (<32K) values, and memory is an issue -- so you'd use 'short' to save memory (or maybe 'char' or 'byte').

2
  • 2
    But with 64-bit, int is hardly ever a good choice, right? I almost always end up using size_t (or even ptrdiff_t!) anyway, to avoid issues with porting code.
    – user541686
    Commented Oct 20, 2011 at 3:07
  • @Merhdad - int used to the best choice it was defn to be the 'standard unit' of the HW, and typically the size of a pointer. Nowadays use size_t for safety. Commented Oct 20, 2011 at 15:19
1

C was designed to actively deal with memory at different levels. There are cases where the difference between short, int, and long, and between float and double, mattered because of memory constraints, architecture, etc. Though it matters less now, there are still environments where it does (e.g, embedded, and in cases where the data is massive), and the transition from mainly 32-bit architectures to 64 bit makes it somewhat of an issue again. (In ten or twenty years when we transition to 128 bit architectures and C/C++ is still popular, it'll again be an issue). You're right though that binary compatibility suffers, which is why you don't want to use these variable type sizes where that matters.

You asked how you would know which to use if you don't know the size, but you do know the size on a given architecture/compiler combination, and if you need to optimize memory at that level, you'd better know it. You can't optimize it that simply across platforms because you can't know their sizes, so you wouldn't want to use those features for that purpose. But a lot of things written in C are platform-specific, which, despite the fashion for "cross platform", does allow for some advantageous optimizations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.