Sample Video Frame
Exercise 21: Advanced Data Types and Flow Control
This exercise will be a complete compendium of the available C data types and flow control structures you can use. It will work as a reference to complete your knowledge, and won't have any code for you to enter. I'll have you memorize some of the information by creating flash cards so you can get the important concepts solid in your mind.
For this exercise to be useful, you should spend at least a week hammering in the content and filling out all of the elements that are missing here. You'll be writing out what each one means, and then writing a program to confirm what you've researched.
Available Data Types
int
: Stores a regular integer, defaulting to 32 bits in size.double
: Holds a large floating point number.float
: Holds a smaller floating point number.char
: Holds a single 1 byte character.void
: Indicates "no type" and is used to say a function returns nothing, or a pointer has no type as invoid *thing
.enum
: Enumerated types, which work as and convert to integers, but give you symbolic names for sets. Some compilers will warn you when you don't cover all elements of an enum inswitch-statements
.
Type Modifiers
unsigned
: Changes the type so that it doesn't have negative numbers, giving you a larger upper bound but nothing lower than 0.signed
: Gives you negative and positive numbers, but halves your upper bound in exchange for the same lower bound negative.long
: Uses a larger storage for the type so that it can hold bigger numbers, usually doubling the current size.short
: Uses smaller storage for the type so it stores less, but takes half the space.
Type Qualifiers
const
: Indicates that the variable won't change after being initialized.volatile
: Indicates that all bets are off, and the compiler should leave this alone and try not to do any fancy optimizations to it. You usually only need this if you're doing really weird stuff to your variables.register
: Forces the compiler to keep this variable in a register, and the compiler can just ignore you. These days compilers are better at figuring out where to put variables, so only use this if you can actually measure an improvement in speed.
Type Conversion
C uses a sort of stepped type promotion mechanism, where it looks at two operands on either side of an expression, and promotes the smaller side to match the larger side before doing the operation. If one side of an expression is on this list, then the other side is converted to that type before the operation is done. It goes in this order:
- long double
- double
- float
- int (but only
char
andshort int
); - long
If you find yourself trying to figure out how your conversions are working in an expression, then don't leave it to the compiler. Use explicit casting operations to make it exactly what you want. For example, if you have:
long + char - int * double
Rather than trying to figure out if it will be converted to double correctly, just use casts:
(double)long - (double)char - (double)int * double
Putting the type you want in parenthesis before the variable name is how you force it into the type you really need. The important thing though is always promote up, not down. Don't cast long
into char
unless you know what you're doing.
Type Sizes
The stdint.h
defines both a set of typdefs
for exact sized integer types, as well as a set of macros for the sizes of all the types. This is easier to work with than the older limits.h
since it is consistent. Here are the types defined:
int8_t
: 8-bit signed integeruint8_t
: 8-bit unsigned integerint16_t
: 16-bit signed integeruint16_t
: 16-bit unsigned integerint32_t
: 32-bit signed integeruint32_t
: 32-bit unsigned integerint64_t
: 64-bit signed integeruint64_t
: 64-bit unsigned integer
The pattern here is in the form (u)int(BITS)_t where a u is put in front to indicate "unsigned," and then BITS is a number for the number of bits. This pattern is then repeated for macros that return the maximum values of these types:
INT(N)_MAX
: Maximum positive number of the signed integer of bits (N), such asINT16_MAX
.INT(N)_MIN
: Minimum negative number of signed integer of bits (N).UINT(N)_MAX
: Maximum positive number of unsigned integer of bits (N). Since it's unsigned, the minimum is 0 and can't have a negative value.
WARNING: Pay attention! Don't go looking for a literal
INT(N)_MAX
definition in any header file. I'm using the(N)
as a placeholder for any number of bits your platform currently supports. This(N)
could be any number, 8, 16, 32, 64, maybe even 128. I use this notation in this exercise so that I don't have to literally write out every possible combination.
There are also macros in stdint.h
for sizes of the size_t
type, integers large enough to hold pointers, and other handy size defining macros. Compilers have to at least have these, and then they can allow other larger types.
Here is a full list should be in stdint.h
:
int_least(N)_t
: Holds at least (N) bitsuint_least(N)_t
: Holds at least (N) bits unsignedINT_LEAST(N)_MAX
: Maximum value of the matching least (N) typeINT_LEAST(N)_MIN
: Minimum value of the matching least (N) typeUINT_LEAST(N)_MAX
: Unsigned maximum of the matching (N) typeint_fast(N)_t
: Similar toint_least*N*_t
but asking for the "fastest" with at least that precisionuint_fast(N)_t
: Unsigned fastest least integerINT_FAST(N)_MAX
: Maximum value of the matching fastest (N) typeINT_FAST(N)_MIN
: Minimum value of the matching fastest (N) typeUINT_FAST(N)_MAX
: Unsigned maximum value of the matching fastest (N) typeintptr_t
: Signed integer large enough to hold a pointeruintptr_t
: Unsigned integer large enough to hold a pointerINTPTR_MAX
: Maximum value of aintptr_t
INTPTR_MIN
: Minimum value of aintptr_t
UINTPTR_MAX
: Unsigned maximum value of auintptr_t
intmax_t
: Biggest number possible on that systemuintmax_t
: Biggest unsigned number possibleINTMAX_MAX
: Largest value for the biggest signed numberINTMAX_MIN
: Smallest value for the biggest signed numberUINTMAX_MAX
: Largest value for the biggest unsigned numberPTRDIFF_MIN
: Minimum value ofptrdiff_t
PTRDIFF_MAX
: Maximum value ofptrdiff_t
SIZE_MAX
: Maximum of asize_t
Register for Learn C the Hard Way
Register today for the course and get the all currently available videos and lessons, plus all future modules for no extra charge.