C Data Types

Integer Types

A data type is really nothing more than an organization of bits.

To demonstrate this idea, it’s visually pleasing to use the stdint.h header file from the C99 Standard Library (or C11 too I suppose).

#include <stdint.h>

This header file provides easy shortcut data types for a certain number of bits:

  int8_t    signed      8-bit
 uint8_t    unsigned    8-bit

 int16_t    signed      16-bit
uint16_t    unsigned    16-bit

 int32_t    signed      32-bit
uint32_t    unsigned    32-bit

 int64_t    signed      64-bit
uint64_t    unsigned    64-bit

If a data type is signed one bit is used to represent that sign, and so the upper limit on that data type is reduced from its unsigned counterpart. We see this in the chart below where the positive value of an unsigned vs signed int falls from 255 (8-bit max) to 127 (7-bit max). The addition of the sign allows for the representation of negative values where necessary.

    Type    Lower Limit                Upper Limit
  int8_t   -128                        127
 uint8_t    0                          255

 int16_t   −32,768                     32,767
uint16_t    0                          65,535

 int32_t   -2,147,483,648              2,147,483,647
uint32_t    0                          4,294,967,295

 int64_t   -9,223,372,036,854,775,808  9,223,372,036,854,775,807
uint64_t    0                          18,446,744,073,709,551,615

Beyond 18,446,744,073,709,551,615 there is only customized support for greater bit-depth using the C language in the form of extensions.

Everything else is semantics and interpretation. When we declare an int, we’re really just asking for a certain number of bits from memory.

Consider the following C program:

#include <stdio.h>
#include <stdlib.h>
int main(void)
   // get the byte-width of a local system int
   printf("sizeof(int): %d bytes\n", sizeof(int));

   // display message
      // 16-bit
      case 2:
         printf("This system uses 16-bit integers\n");
      // 32-bit
      case 4:
         printf("This system uses 32-bit integers\n");
      // 64-bit
      case 8:
         printf("This system uses 64-bit integers\n");
      // 128-bit
      case 16:
         printf("This system uses 128-bit integers\n");
      // default
         printf("Unable to determine byte width of int\n");

   // success
   return 0;

And its output:

$ ./this 
sizeof(int): 4 bytes
This system uses 32-bit integers

This bit of logic demonstrates that on this system the bit width of a single int is 32-bits or 4 bytes.

The common C data types and their aliases are listed here. Note that each data type has a minimum specification for value.

Despite the minimum 16-bit requirement for integers declared using int, some systems will return larger spaces and so overflow situations will differ between the smaller and larger numbers.

Intel C8008 8-bit Microchip

Its important to know what the limitations of each system are before developing for it. Certain systems may be limited to 16-bit or even 8-bit blocks.

Note also how many different aliases there are for each bit-width and what their format specifiers are.

Data Types & Format Specifiers

Data Type (alias) Format Specifier
char %c
signed char %c (or %hhi for numerical output)
unsigned char %c (or %hhu for numerical output)
short int
signed short
signed short int
unsigned short
unsigned short int
signed int
%i or %d
unsigned int
long int
signed long
signed long int
unsigned long
unsigned long int
long long
long long int
signed long long
signed long long int
unsigned long long
unsigned long long int

Range and Precision

In mathematics we have numbers with fractions, and thus an integer with a decimal and more digits stuck to it. These kinds of numbers are managed differently from integers to accommodate a balance of range and precision and have special declarations, though they still ultimately refer to a certain bit-width in memory.

float for formatted input:
%f %F for digital notation, or
%g %G, or
%e %E
%a %A
for scientific notation
double %lf %lF
%lg %lG
%le %lE
%la %lA;for formatted output, the length modifier l is optional.
long double %Lf %LF
%Lg %LG
%Le %LE
%La %LA

The only reason any series of bits has any relevance is because its mapped to a context. This is how we’re able to have a float of value 1.1 and to be able to contextually perform calculations with this value within the C language syntax.

Floating-point numbers are so-called because they are structured with a floating radix point to represent numbers as decimals in the context of scientific notation.

Every new variable in C has is declared first by using its data type:

Data Type     Context
int           Integer
long          Larger Integer
float         Floating-Point Number
double        Larger Floating-Point Number

Leave a Reply

Your email address will not be published. Required fields are marked *