Appendix A: Data Types and Compatibility

As we consider data types in C and how they are compatible with each other, let's recall the rules of compatibility. Here are a few notes:

  1. C uses static typing, which dictates that the types of variables are derived once (at declaration) and do not change throughout the execution of a program.
  2. C uses strong typing, which means that once variables are bound to a data type (at declaration), they stay bound to that type. They cannot not change types, but require values to be converted to their data type before they are assigned.
  3. In general, type A is compatible with type B when (a) the operations of A are also the operations of B and (b) the values that variables of type A can have are at least a subset of the values that variables of type B can have.
  4. Type modifiers have an effect on the values that a variable can take on and, thus, affect type compatibility.

The table below contains modifiers where appropriate. These modifiers are:

  • "signed" and "unsigned": This determines the capability to represent negative numbers. Unsigned types are not wider than signed types, but they represent different number ranges.
  • "short": This typically specifies a width that is half of the type it modifies.
  • "long": This modifier represents a width double the width of the type it modifies.
TypeDescriptionCompatibility
char Single byte units with characters as their value. On Pebble OS, these values come from the Unicode character set. While characters can be converted to integers, they do not have a sign bit. This means the integer range is 0 to 255. Any numeric type
signed char Single byte units, represented as integers. Signed char types have a range from -127 to 128. Any numeric type
unsigned char Single byte units, represented as numbers without a sign bit. This is the same as the `char` type. Integer range is 0 to 255. Any numeric type
int
signed
signed int
Representation of standard integer. On Pebble OS, this type is 32 bits wide and uses 2's complement for negative representation. Range is -231-1 to +231. Any numeric type
short
short int
signed short
signed short int
Representation of a signed integer. It is usually half the width of integers; on Pebble OS, this is 16 bits. Range is -32,767 to 32,768. Uses 2's complement for negative representation. Any numeric type
unsigned short
unsigned short int
Representation of an unsigned integer. It is usually half-width with no sign; on Pebble OS, this is 16 bits. Range is 0 to 65,535. Any numeric type
long
long int
signed long
signed long int
This represents a signed double width integer. On Pebble OS, the width is the same as signed integers: 32 bits (which is allowed by the C standard). Range is -231-1 to +231. It uses 2's complement for negative representation. Any numeric type
unsigned long
unsigned long int
Representation of an unsigned long integer. This is usually double the width of an unsigned integer, however on Pebble OS this is 32 bits. Range is 0 to +232-1. Any numeric type
long long
long long int
signed long long
signed long long int
This represents a signed double long integer. It can be double to quad width; on Pebble OS, it is 64 bits. Range is -263-1 to +263 Uses 2's complement for negative representation. Any numeric type
unsigned long long
unsigned long long int
Representation of an unsigned double long integer. This is usually double the long width; on Pebble OS, this means 64 bits. Range is 0 to +264-1. Any numeric type
float Single precision floating point number, 32 bits wide in IEEE 754 format. All float types are signed. Other float types
double Double precision floating point number. 64 bits wide in IEEE 754 format for double precision numbers. All float types are signed. Other float types
long double Extended, or quadruple, precision floating point numbers, 128 bits wide in IEEE 754 format for quadruple precision numbers. All float types are signed. Other float types
_Bool
bool
Represents boolean values. Includes macros for true and false. Part of the C standard, but not included in Pebble SDKs. numeric types

We can write a smartwatch app to see how these definitions are implemented on a Pebble smartwatch. You can view and run the code yourself in CloudPebble with this link, but the relevant snippet is shown below. The output is done using the APP_LOG macro.

static void display_chars() {    
    APP_LOG(APP_LOG_LEVEL_INFO, "\nCHARACTER SIZES\n   char = %d, max char = %d\n   unsigned char = %d", 
            sizeof(char), CHAR_MAX, sizeof(unsigned char));
}

static void display_integers() {
    APP_LOG(APP_LOG_LEVEL_INFO, "\nINTEGER SIZES\n   short = %d, max short = %d\n   int = %d, max int = %d", 
            sizeof(short int), SHRT_MAX, sizeof(int), INT_MAX);
    APP_LOG(APP_LOG_LEVEL_INFO, "\n   unsigned short = %d, max unsigned short = %d", 
            sizeof(unsigned short int), USHRT_MAX);
    APP_LOG(APP_LOG_LEVEL_INFO, "\n   unsigned int = %d, unsigned max int = %u", 
            sizeof(unsigned int), UINT_MAX);
    APP_LOG(APP_LOG_LEVEL_INFO, "\n   long = %d, max long = %li\n   long long = %d, max long long = %lli", 
            sizeof(long), LONG_MAX, sizeof(long long), LLONG_MAX);
    APP_LOG(APP_LOG_LEVEL_INFO, "\n   unsigned long = %d, unsigned max long = %lu", 
            sizeof(unsigned long), ULONG_MAX);
    APP_LOG(APP_LOG_LEVEL_INFO, "\n   unsigned long long = %d, max unsigned long long = %llu", 
            sizeof(long long), ULLONG_MAX);
}

The code measures size of each type by using the sizeof() operator, which measures in bytes. The output of display_chars() is given below (cleaned up from the log display) and shows that character and unsigned character types match up with the table above. Both are single bytes wide.

CHARACTER SIZES
   char = 1, max char = 255
   unsigned char = 1

The size of short and regular integers, as well as the maximum values, are also in line with the table above. As we described, there is no difference long integers and regular integers. The size and max value of regular integers and long integers (and their unsigned counterparts) are the same. Based on long integers, long long integers are on track: double the size and their max values match accordingly. The output for display_integers() is below:

INTEGER SIZES
   short = 2, max short = 32767
   int = 4, max int = 2147483647
   unsigned short = 2, max unsigned short = 65535
   unsigned int = 4, unsigned max int = 4294967295
   long = 4, max long = 2147483647
   long long = 8, max long long = 92233720368547758
   unsigned long = 4, unsigned max long = 4294967295
   unsigned long long = 8, max unsigned long long = 18446744073709551615

Notice that we did not compute the max values, but rather used defined constants. Every C compiler has a set of constants defined that outline the maximum values for that installation.

Also note that we did not test floating point numbers. As pointed out in Chapter 3, floating point numbers are difficult for small embedded processors like those in Pebble smartwatches.

results matching ""

    No results matching ""