What Size Integer?

Things were stable back in the old days. When I first coded C, a char was 8-bits (a byte), and an int was 16-bits. The short was also 16-bits and the long, it was truly long at 32-bits. Today, things aren’t as consistent.

The problem is that no true standard exists for the size of a C language integer data type. The only constant is that a char is still a byte, an 8-bit value. Otherwise, to determine the size of things for a given compiler, you can run this code:

2020_07_04-Lesson-a.c

#include <stdio.h>

int main()
{
    printf("char is %lu bits\n",sizeof(char)*8);
    printf("short is %lu bits\n",sizeof(short)*8);
    printf("int is %lu bits\n",sizeof(int)*8);
    printf("long is %lu bits\n",sizeof(long)*8);
    printf("long long is %lu bits\n",sizeof(long long)*8);

    return(0);
}

Each printf() statement takes a given integer data type and outputs its bit width. The sizeof operator returns the size in bytes, which are assumed to be 8-bits wide. The %lu placeholder handles the long unsigned value returned from the sizeof operator.

The output on my iMac appears as follows:

char is 8 bits
short is 16 bits
int is 32 bits
long is 64 bits
long long is 64 bits

Decades ago, a short and an int were the same size. No more! On the Mac, a long is 64 bits — and so is the long long. On some systems, the long long might be 128 bits. Who knows?

Well, the compiler knows, of course. The sizeof operator returns the width. Constants declared in the limits.h header file also help with determining the maximum values that certain data types can handle.

Beyond these tidbits, you can use special defined types that predicate their bit width right in the type definition. They are:

int8_t, an 8-bit integer
int16_t, a 16-bit integer
int32_t, a 32-bit integer
int64_t, a 64-bit integer

These typedefs are available in the stdint.h header file, which you need not include directly as (I believe) stdio.h includes them automatically. Regardless, these types define precise bit widths as their names imply. No matter how the compiler interprets a short, int, or long, these data types remain consistent, as this sample code demonstrates:

2020_07_04-Lesson-b.c

#include <stdio.h>

int main()
{
    printf("int8_t is %lu bits\n",sizeof(int8_t)*8);
    printf("int16_t is %lu bits\n",sizeof(int16_t)*8);
    printf("int32_t is %lu bits\n",sizeof(int32_t)*8);
    printf("int64_t is %lu bits\n",sizeof(int64_t)*8);

    return(0);
}

The output:

int8_t is 8 bits
int16_t is 16 bits
int32_t is 32 bits
int64_t is 64 bits

There. Consistency.

Two variations exist for each of these defined data types, least and fast. The least version ensures that the values use at least the bit width specified:

int_least8_t, at least an 8-bit integer
int_least16_t, at least a 16-bit integer
int_least32_t, at least a 32-bit integer
int_least64_t, at least a 64-bit integer

For example, int_least8_t has a minimum width of 8-bits.

I’m unsure what the fast variation does:

int_fast8_t, a fast 8-bit integer
int_fast16_t, a fast 16-bit integer
int_fast32_t, a fast 32-bit integer
int_fast64_t, a fast 64-bit integer

Internally and at least on the Mac, the stdint.h header typedef’s all these variations to the basic definitions. These types most likely exist for compatibility purposes only.

Another data type not yet available in C is the variable width integer. The varint declares its bit width and then ensures that all declared variables use the given width. This additional data type sounds interesting and would be a fun addition to C in the future.

Leave a Reply