views:

62

answers:

4

stdint.h in C99 provides many options for integer sizes, types and ranges - so many I don't know what ones to choose!

I know how to use size_t and ptrdiff_t when appropriate, and I use fixed size types for storage and transmission. My question concerns values that will only be stored in memory of the host machine.

For example, a structure for an image might contain these members:

struct image {
    integer width, height; /* pixel dimensions of the image */
    integer bits_per_pixel;
    ...
};

If width and height will never exceed SHRT_MAX, should a short be used, or stick with int? An image can't have negative width or height, so use an unsigned type? Perhaps (u)int_least16_t is the correct choice? Something else?

If bits_per_pixel will never exceed a value of 64 use char, unsigned char, uint8_t, int or something else?

What would you use in this example and why?

How does the CPU architecture the code will run on affect the choice? i.e. PPC or x86, 32 or 64bit.
How does the device the code will run on affect the choice? i.e. Desktop, phone, console.
How does the choice relate to performance and optimization?

My question in simple terms is: How do you choose which integer to use?

+4  A: 

I would say: Don't worry to much about this, it often is a form of premature optimisation. But my rules of thumb are:

  • Use plain int when possible. It should be the natural word size of the machine.
  • Use unsigned types when you need well-defined integer overflow.
  • Use an (u)intX_t type when you need two's-complement representation.
  • Use unsigned char for large arrays with values <= UCHAR_MAX.

Beware that a lot of the types in <stdint.h> are optional, so you can't depend on their existence. POSIX makes this slightly better.

schot
+1  A: 

There are no hard and fast rules.

If you choose a type too small, you can end up artificially limiting the data sets that your program can handle. Too big, and your performance may suffer.

Unless you are running in to performance problems for your specific task, I would definitely lean towards "too big". While using an integer for bits/pixel is kind of silly, it probably wont hurt anything in the greater scheme of things.

nsanders
+1  A: 

Unless your application is really memory intensive, don't worry about sizes and use int. Using short or char can cause subtle bugs which may cause problems later. Also, using char or short won't gain you any additional CPU cycles.

kaustubh
+3  A: 

For your example, I would simply use int or (perhaps better) unsigned for all three fields. There is no sense using smaller types except in an array that will contain thousands or millions of elements; it just imposes artificial limits.

To answer the more general question, here are some guidelines I go by:

  • Always choose the correct signedness for the values you'll be storing.
  • For object counts, indices, lengths of strings/data in memory, etc. use size_t.
  • For data that has a particular range of values that you need to be able to store, and where you'll never need to store values outside than range, use one of the fixed-size integer types from stdint.h (uint8_t, uint16_t, uint32_t, etc.). The common examples of this sort of need that come to mind are pixel values, audio samples, and Unicode characters (typically 8, 16, and 32 bit, respectively).
  • Otherwise, int or unsigned is probably the right type to use.
R..
+1 for the fixed-size data examples.
schot