C sizes

Paper by khorben
on Saturday, April 8 2006
Why the fuzz?

If you have the chance to be an experienced C programmer, or otherwise be familiar with the C language definition, you may be aware of this part of the ANSI C standard [1]:

5.2.4.2.1  Sizes of integer types <limits.h>

[#1]  The  values  given below shall be replaced by constant
expressions  suitable   for   use   in   #if   preprocessing
directives.   Moreover,  except for CHAR_BIT and MB_LEN_MAX,
the following shall be replaced by expressions that have the
same  type  as  would an expression that is an object of the
corresponding  type  converted  according  to  the   integer
promotions.   Their  implementation-defined  values shall be
equal or greater in  magnitude  (absolute  value)  to  those
shown, with the same sign.
And to be complete:

6.3.1.1  Boolean, characters, and integers

[#1]  Every  integer  type  has  an  integer conversion rank
defined as follows:

  -- No two signed integer types shall have the  same  rank,
     even if they have the same representation.

  -- The rank of a signed integer type shall be greater than
     the  rank  of  any  signed  integer  type   with   less
     precision.

  -- The  rank  of  long  long int shall be greater than the *
     rank of long int, which shall be greater than the  rank
     of  int,  which shall be greater than the rank of short
     int, which shall be greater than  the  rank  of  signed
     char.
The last sentence of the first excerpt means, if I am correct, that essential scalar types in C have an undetermined size. They just have to hold at least:
Platform |char  |short |long  |long  |int   |float |double|Notes
         |      |      |      |long  |      |      |      |
ANSI C   |8     |16    |32    |64    |16    |32    |64    |
So, what's that all about? Well, these days are critical for applications developers, as more and more hardware can be found with native 64 bits processors. However, such an environment may be new to some developers. So, stay tuned for some ÜberWall tricks and tips.

Comparison chart

The following table contains the actual values we have observed on the architectures we have come across:
Reminder: do NOT rely on results from this table
Platform          |char  |short |long  |long  |int   |float |double|Notes
                  |      |      |      |long  |      |      |      |
FreeBSD 6/gcc/x86 |8     |16    |32    |64    |32    |32    |64    |
Linux/gcc/x86     |8     |16    |32    |64    |32    |32    |64    |
Linux/gcc/x86-64  |8     |16    |64    |64    |32    |32    |64    |
NetBSD/gcc/sparc  |8     |16    |32    |64    |32    |32    |64    |
NetBSD/gcc/sparc64|8     |16    |64    |64    |32    |32    |64    |
Solaris 10        |8     |16    |32    |64    |32    |32    |64    |Defaults to
/gcc/sparc64      |      |      |      |      |      |      |      |ELF 32-bit
Solaris 10        |8     |16    |64    |64    |32    |32    |64    |With -m64
/gcc/sparc64      |      |      |      |      |      |      |      |ELF 64-bit
Windows NT 5.0    |8     |16    |32    |64    |32    |32    |64    |
/Dev-C++/x86-64   |      |      |      |      |      |      |      |
If you think you can contribute interesting results, you can use the following C program to help:
#include <stdio.h>
#define type(a) printf("sizeof(%s) = %u\\n", "" # a, sizeof(a) * 8);
int main(void)
{
    type(char);
    type(short);
    type(long);
    type(long long);
    type(int);
    type(float);
    type(double);
    return 0;
}
Note that this program may indeed trigger warnings on sizeof() result size.

Send your results and reactions to khorben [2]. Feel free to send results for any platform unlisted.

Conclusion

What's the morale in this? Think twice before trusting the sizes of the basic data types in C: you may use <stdint.h> instead.

[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/text/n843.txt
[2] mailto:khorben awt uberwall dowt org