Monday, July 30, 2012

C Enumeration

    Enumerated data types in C allow us to assign names to a set of integer values.  This new data type can be given its own name as well.  This post will discuss basic enumeration, the #define statement, values in hexadecimal, and using single bits as flags.

Enumeration:
    If you have a list of possible choices which are not necessarily numbers, then enumeration can help the code show these possibilities.  As an example, if you want to select only one color from a set of defined colors, then you can create an enumeration called color.  Then give names like red, yellow, green, and blue to values like 0, 1, 2, and 3.

    Here is an example function which has a color type as a parameter:
#include <stdio.h>

//use color in place of enum color
typedef enum color color;

enum color {
    red, //is given value 0
    yellow, // == 1
    green, // 2
    blue // 3
};

//a function that prints the chosen color
void choose_color(color selection) {
    switch(selection) {
    case red: //if (selection == red)
        printf("red selected\n");
        break;
    case yellow: //else if (selection == yellow)
        printf("yellow selected\n");
        break;
    case green:
        printf("green selected\n");
        break;
    case 3:
        printf("blue selected\n");
        break;
    default: //else
        printf("unknown selection\n");
        break;
    }
}

int main() { //select three colors
    choose_color(red);
    choose_color(1); //could put yellow instead
    choose_color(blue);

    getchar();
    return 0;
}
output in prompt:
red selected
yellow selected
blue selected


    By creating the enum color and using typedef, color is now a unique type of data.  The function choose_color creates the variable selection of type color using input and compares its value to those found in the enum color list.  Notice that the term red is now interchangeable with the value 0, which means no variable should be named red.

    Although colors are used in this example, enumerations can be used for many sets of choices: directions, months, locations, shapes, etc.  Usually, each individual choice excludes the others; one cannot be in two locations or in two months at the same time.  Luckily, whole numbers work the same way in that each value is unique.

    There is also an alternative to creating an enum which is to use #define.  The #define statement is similar to the find and replace option found in text editors because it will replace the first parameter with the second.  If you wanted to replaced the name red with 0, you would use "#define red 0".

    Here is an alternative to the previous example:
#include <stdio.h>

#define red 0 //replace all red with 0
#define yellow 1 //yellow becomes 1
#define green 2 //green becomes 2
#define blue 3 //blue becomes 3

//a function that prints the chosen color
void choose_color(int selection) {
    switch(selection) {
    case red: //if (selection == red)
        printf("red selected\n");
        break;
    case yellow: //else if (selection == yellow)
        printf("yellow selected\n");
        break;
    case green:
        printf("green selected\n");
        break;
    case 3:
        printf("blue selected\n");
        break;
    default: //else
        printf("unknown selection\n");
        break;
    }
}

int main() { //select three colors
    choose_color(red);
    choose_color(1);
    choose_color(blue);

    getchar();
    return 0;
}
output in prompt:
red selected
yellow selected
blue selected


    Since there is no enum called color this time, the variable selection (in function choose_color) is of type int.  Also, there is no need for the typedef statement from before.  While this is mostly positive, the one negative side effect is that NO variable can be named red, yellow, green, or blue because it will be replaced with 0, 1, 2, or 3.  One way around this is to make the color names look less "variable-ish", like using all capital letters and possibly adding a prefix like COLOR_ to each choice.

Flags:
    Unlike enumerations that exclude each other, flags use bits to allow for more possibilities.  Each bit can be used to determine whether a choice is selected or not, but each selection does not exclude others.  One way to access individual bits easily is to use hexadecimal values.

    Where decimal uses 0-9 and binary only uses 0 and 1, hexadecimal uses 0-9 as well as a-f.  The hexadecimal value a equals 10 in decimal and f is 15 in decimal.  To translate a hexadecimal value into decimal, multiply each number by a power of sixteen.  For example, hexadecimal c5 = c * 16^1 + 5 * 16^0 = 12 * 16 + 5 * 1 = decimal 197.

    For flags, you need to use powers of two for each choice.  This allows the use of individual bits (1 = 00000001, 2 = 00000010, 4 = 00000100, etc.) which can then be added together.  The reason hexadecimal is helpful is because its powers of sixteen are divisible by several powers of two, and are also a power of two themselves.  This allows for easier setting of bits, as seen in the following table:

decimal valuebinary (8 bits)hexadecimal
10000000101
20000001002
40000010004
80000100008
15000011110f
160001000010
320010000020
640100000040
1281000000080
24011110000f0
25511111111ff

    This table assumes that the value is unsigned (for signed, the last three would be -128, -16, and -1).  While there are patterns in the binary and decimal numbers, there is an easier to see pattern in the hexadecimal and binary numbers: each hexadecimal number affects 4 bits.  We only have to remember 1, 2, 4, and 8 as powers of two.

    If each choice is assigned a power of two, we can add the selected choices (or use bitwise or) and get a set of bits which correspond to the selections.  To retrieve the choices from the bits, we can use bitwise and.  Here is an example with some possible choices one may find in an application:
#include <stdio.h>

//features and enum features synonymous
typedef enum features features;

//for hexadecimal values, 0x is placed in front
enum features { //manually assign values
    subtitles = 0x01,
    music = 0x02,
    sound_effects = 0x04,
    multiplayer = 0x08
};

/* input a set of bits (in int form)
   and the function says which features
   are selected (by checking bits).
*/
void select_features(int flags) {
    printf("Features selected:\n");

    if ((flags & subtitles) != 0) {
        printf("-subtitles\n");
    }

    if ((flags & music) != 0) {
        printf("-music\n");
    }

    if ((flags & 0x04) != 0) {
        printf("-sound effects\n");
    }

    if ((flags & multiplayer) != 0) {
        printf("-multiplayer\n");
    }

    printf("\n");
}

int main() {
    /*make three selections of multiple
      choices, zero being none*/
    select_features(music | subtitles);
    select_features(multiplayer + music);
    select_features(0x0f);

    getchar();
    return 0;
}
output in prompt:
Features selected:
-subtitles
-music

Features selected:
-music
-multiplayer

Features selected:
-subtitles
-music
-sound effects
-multiplayer



    The first change you may notice is that values can be assigned to the list of enumerated values.  This is useful since we must use powers of two, which are in hexadecimal for this example.  The hexadecimal is not exactly useful in this case, but if another feature is added, the next hexadecimal value would be 0x10.  Also, since an int is usually 32 bits, you can replace 0x10 with 0x00000010 (8 hexadecimal places, each of which control 4 bits).

    Each select_features call in the main function allows us to simply list which features we want to use.  We can use bitwise or (|), addition(+), or even a number to  indicate the selected features.  This type of input will be common in libraries like SDL, OpenGL, and OpenAL.

    The input for the function select_features is not of the variable type features.  An integer is used to allow operations like addition and bitwise or unlike created data types.  Also, the resulting number may not be one of the power-of-two elements in the enum list.  Since this is not a great use of enumeration, most libraries will use #define for flags.

    Here is a similar example using #define:
#include <stdio.h>

/* will replace the following names
   with integer values */
#define FEAT_SUBS 0x01 //8-bit hexadecimal
#define FEAT_MUSIC 2 //decimal
#define FEAT_SOUNDFX 0x04
#define FEAT_MULTI 0x00000008 //32-bit

//tell which features are selected
void select_features(int flags) {
    printf("Features selected:\n");

    if ((flags & FEAT_SUBS) != 0) {
        printf("-subtitles\n");
    }

    if ((flags & FEAT_MUSIC) != 0) {
        printf("-music\n");
    }

    if ((flags & FEAT_SOUNDFX) != 0) {
        printf("-sound effects\n");
    }

    if ((flags & FEAT_MULTI) != 0) {
        printf("-multiplayer\n");
    }

    printf("\n");
}

int main() {
    /*make three selections of multiple
      choices, zero being none*/
    select_features(FEAT_MUSIC | FEAT_SUBS);
    select_features(FEAT_MULTI + FEAT_MUSIC);
    select_features(0x0f);

    getchar();
    return 0;
}
output in prompt:
Features selected:
-subtitles
-music

Features selected:
-music
-multiplayer

Features selected:
-subtitles
-music
-sound effects
-multiplayer



    The names in the program have been changed to reflect the style a library like SDL uses.  The features are still given the same values: 1, 2, 4, and 8, the first four powers of two.  The same selections from the previous program are made and the same results occur, however the code is slightly shorter and no new data types are introduced.

    For more information about enumerated types, go to http://cplus.about.com/od/introductiontoprogramming/p/enumeration.htm and http://www.cprogramming.com/tutorial/enum.html.  For a guide to hexadecimal, the page http://www.myhome.org/pg/numbers.html should help.

    Thank you for reading, the next post will begin the SDL posts!  This does not mean the end of the C posts, but they will be less frequent.  For more C, there are the pages http://www.acm.uiuc.edu/webmonkeys/book/c_guide/, http://beej.us/guide/bgc/output/html/multipage/index.html, and http://www.cprogramming.com/tutorial/c-tutorial.html.

Thursday, July 19, 2012

Strings in C

    One popular use of pointers is strings, the data type for text.  Until now, all data and commands have dealt with numbers, but strings allow storage of messages and names.  This is accomplished with an array of characters, or char variables.  This post will discuss the char data type and char arrays.

The char type:
    A char is a whole number with the range of values -128 to 127 if it is signed or 0 to 255 if unsigned.  This value can be used as a number as well as a single letter.  ASCII is used to convert a number into a letter or symbol: 65-90 become upper case A-Z and 97-122 become a-z.  A full table can be found at http://www.asciitable.com/.

    To print the symbol or letter form of a character, use the %c marker with printf.  The ASCII values 48-57 are used for the number symbols 0-9, so be careful not to confuse this output with the numeric value of the character.  Also, the symbols with values outside the range 0-127 will depend upon the standard used by a country.

    If you don't want to memorize the ASCII values of a symbol, C allows us to assign symbols straight to chars.  Here is a demonstration.
#include <stdio.h>

int main() {
    char letter = 'g';
    char symbol = 47; //no single-quotes
    char number = '3'; //single quotes

    //%c for the symbol, %d or %u for its value
    printf("%c in ASCII: %d\n", letter, letter);
    printf("%c in ASCII: %d\n", symbol, symbol);
    printf("%c in ASCII: %d\n", number, number);

    getchar();
    return 0;
}

output in prompt:
g in ASCII: 103
/ in ASCII: 47
3 in ASCII: 51


    The char letter is assigned the value 103, or the ASCII value of the lower-case letter g.  By placing single quotes around a keyboard symbol, C will convert the symbol into its ASCII code automatically.  Notice that the symbol 3 has a numeric value of 51: it is best to remember which is the ASCII code and which is the symbol.

Strings:
    By placing a collection of these characters into an array, we can create a string.  This can hold a word, a sentence, a sequence of numbers, and anything else you can type into a text editor.  Strings can be placed in either static or dynamic arrays.

    Since strings can be placed in dynamic arrays, there exists a way to track their length.  Every C string ends with an additional null character to indicate there is no more data.  A null character has the numeric value 0 and can be represented as '\0' in symbol form.  The \ in front is the same used by the character '\n'.

    Once you have a sequence of characters in an array ending with the null character, you can print the string.  Use the %s marker in printf to print the string, but it only stops at the end if there is a null character.  Also, an additional string library (string.h) contains the strlen function which finds length of a string.  It too stops at the null character, but does not count it.

    Now, to demonstrate how strings can be created and printed, here are three ways to say hello:

#include <stdio.h>
#include <stdlib.h>
#include <string.h> //full of string functions

char* quotes = "hello";
char static_array[] = {'h','e','l','l','o','\0'};
char* dynamic; //will copy from static

int main() {
    int index;
    int size = strlen(static_array);

    printf("string length = %d\n", size);
    size += 1; //size to include null char

    dynamic = (char*)malloc(size * sizeof(char));

    for (index = 0; index < size; ++index) {
        dynamic[index] = static_array[index];
    }

    //print all forms of hello
    printf("quotes: %s\n", quotes);
    printf("static: %s\n", static_array);
    printf("dynamic: %s\n", dynamic);

    //remove dynamic from memory
    free(dynamic);

    getchar();
    return 0;
}

output in prompt:
string length = 5
quotes: hello
static: hello
dynamic: hello


    The static array is assigned a set of values.  This method of assigning values does not require us to specify a size and only works for statically allocated arrays.  Elements are between { and } and separated by commas.  Basically, static_array is given the character symbols h, e, l, l, o, and null, making it six elements long.  No additional work is needed and static_array is ready to print.

    The elements of the dynamic array are given the characters in the static array.  First, we find the size of the static_array string (which could be found with "sizeof(static_array) / sizeof(*static_array)", but strlen works too).  Then, we allocate memory and copy over each character, including the null character.  Finally, dynamic is ready to print and must be removed from memory before exiting.

    The quotes are used to create a statically allocated array ending with '\0', which means the quotes array is ready to print.  The quotes also make the array unmodifiable.  Unlike static_array whose elements can be changed and used, the quotes array elements can only be read, not assigned values to.  For example, the value quotes[3] can be assigned to another variable, but "quotes[3] = 'i';" is not valid.

    This type of array is placed in a different part of memory which can only be read from.  It is referred to as a non-volatile, or const, array.  By placing variables in 'const' memory, you allow them to only be given a value once, but that value can be used at any time.  For more information on const variables, check out the page http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html.  Remember that this is a property of the array itself, the variable quotes just happens to point to this array.

    The quotes array is also ready to print without much work.  In fact, the same type of strings are used as the first parameter in the printf commands above because of their easy setup.  The const array strings can also be used in the strlen function to find their length (as well as strings in dynamic arrays).  Like the statically allocated arrays, we do not need to remove them from memory.

    For the final example, here is a program that merges two strings together with sprintf:

#include <stdio.h>  //printf and sprintf
#include <stdlib.h> //malloc and free
#include <string.h> //strlen

//for multiple pointers, each needs an *
char *hello = "hello ", *world = "world!";
char* text; //message to print

int main() {
    int size = strlen(hello);
    size += strlen(world);
    size += 1; //for the null character

    text = (char*)malloc(size * sizeof(char));

    //output goes to string, not prompt
    sprintf(text, "%s%s", hello, world);

    printf(text); //output message
    free(text); //remove from memory

    getchar();
    return 0;
}

output in prompt:
hello world!


    The sprintf function allows us to place a string which would normally print in the prompt and place it into a string array.  Here, the strings hello and world are printed side-by-side and put into the text array.  The sprintf function places a null character at the end automatically, just be sure the array has enough space.

    For more information about C strings, you can read the page http://www.cprogramming.com/tutorial/lesson9.html and see a reference of the functions found in string.h at http://www.cplusplus.com/reference/clibrary/cstring/.  The next post will be about enumerated types and flags, then onto SDL!

Wednesday, July 11, 2012

Pointers in C

    All forms of data in C are assigned an address in memory.  This address allows access to the value or values stored inside which may be read or overwritten with new values.  This concept is key for understanding C, so please check out the pages http://pw1.netcom.com/~tjensen/ptr/pointers.htm, http://boredzo.org/pointers/, and http://www.cprogramming.com/tutorial/c/lesson6.html for truly well-done tutorials.  This tutorial will attempt to demonstrate references and arrays, both of which use pointers.

Reference:
    One way to use pointers is to refer to data stored somewhere in memory.  Each memory address has a numeric value and each variable initialized in C is placed in a numbered address.  You can determine the address of a variable by using the reference operator(&) and assigning the numeric address to a variable called a pointer.

    A pointer can have several types: int*, float*, unsigned short*, char*, etc. all of which are the address of the type and not the type itself.  The following example shows how to use pointers to change variables stored in memory:
#include <stdio.h>

//wait_key prototype
int wait_key();

int main() {
    int a = 5; //int a
    int *b; //int pointer b

    b = &a; //b is given address of a
    *b = 3; //address at b given value

    printf("a = %d\n", a); //a changed

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
a = 3



    The int a is given a value of 5 and the int pointer b is given the address, or reference, of a.  The * in front of b is called the de-reference operator and gives access to the value at the pointer's address.  For this example, 3 is assigned to the value where a is stored, which overwrites the 5 value to 3.

    Pointers can also be input for functions.  Any changes made to the value of a pointer in a function can be seen in other functions, similar to a global variable.  Here is an alternative version of the make_rectangle function from the previous post:
#include <stdio.h>

//alternative name for struct rectangle
typedef struct rectangle rectangle;

//wait_key prototype
int wait_key();

//definition of rectangle data type
struct rectangle {
    int width, height;
};

/* pointer p recieves value of r, set inner
variables found at address p */
void make_rectangle(rectangle* p, int w, int h) {
    (*p).width = w;
    p->height = h; // p-> == (*p).
}

//get inner variables at address p, multiply
int get_area(rectangle* p) {
    int area = p->width;
    area *= (*p).height;
    return area;
}

int main() {
    rectangle r;
    int area;

    //use reference of r as input
    make_rectangle(&r, 4, 5);
    //print changed r
    printf("r: %d x %d\n", r.width, r.height);

    area = get_area(&r);
    printf("area = %d\n", area);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
r: 4 x 5
area = 20


    The function make_rectangle no longer creates and returns a rectangle, instead it modifies an existing rectangle.  A more appropriate name for this version may be set_rectangle, and the name get_area works for the second function since it still returns an integer representing the rectangle area.

    Even though the rectangle r was created in main, its members can be accessed by other functions with the use of a pointer.  This access allows make_rectangle to set the width and height of r, and get_area to use its width and height.

 Array:
    While pointers can be used to access a single value or data type, they can also refer to a collection of many values called an array.  The pointer will refer to the first element of the array and you can access the other elements from it.  Arrays can either be statically or dynamically placed in memory.

    A statically allocated array will remain the same size until the program quits.  The following example will create an array of 5 integers:
#include <stdio.h>

//wait_key prototype
int wait_key();

int main() {
    int index, size;
    int numbers[5]; //five integers

    //assign each integer a value
    for (index = 0; index < 5; index += 1) {
        numbers[index] = 2 * index + 1;
    }

    //make specific changes
    numbers[3] = 6;
    numbers[2] = numbers[3];

    //print values
    for (index = 0; index < 5; index += 1) {
        printf("numbers[%d] = %d\n",
            index, numbers[index]);
    }

    //size of the static array
    size = sizeof(numbers) / sizeof(*numbers);
    printf("# of elements = %d\n", size);

    //numbers points to the first element
    printf("*numbers = %d\n", *numbers);

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
numbers[0] = 1
numbers[1] = 3
numbers[2] = 6
numbers[3] = 6
numbers[4] = 9
# of elements = 5
*numbers = 1


    When created, the variable 'numbers' is an array of five integers with five unspecified values.  A simple for loop from 0 to 4 allows us to initialize each element's value using [ and ] around a number.  This index number is how many spaces from the first element you wish to move: 0 is still the first element and moving 4 over gives us the fifth and final element.

    A quick warning: always track how big your array is and avoid using an index number outside the range 0 to (number of elements - 1).  An index beyond these bounds can access other, irrelevant parts in memory and even change them.  Newer operating systems tend to prevent pointers accessing the memory of other programs, but you want to avoid corrupting your own program's data.  One nice feature of static arrays is the ability to find their size.

    The expression "sizeof(numbers) / sizeof(*numbers)" tells us the number of integers in the array variable 'numbers'.  First, we find the size of the entire array in bytes (the sizeof command).  Since integers require 4 bytes, we also divide by the number of bytes a single element requires.  We could also divide by sizeof(int), but the original expression also finds the number of elements for other types of arrays (double, short, etc.).

    Dynamically allocated arrays require an additional header file called stdlib.h (the C standard library).  This additional library includes the commands malloc and free to enable creating and removing arrays at any point during the program.  Aside from these commands, the syntax is similar to static arrays:
#include <stdio.h>
#include <stdlib.h> //malloc and free

//wait_key prototype
int wait_key();

int main() {
    int index, size;
    int *numbers; //pointer to integer

    numbers = (int*)malloc(5 * sizeof(int));
    size = 5;

    //assign each integer a value
    for (index = 0; index < 5; index += 1) {
        numbers[index] = 2 * index + 1;
    }

    //make specific changes
    numbers[3] = 6;
    numbers[2] = numbers[3];

    //print values
    for (index = 0; index < 5; index += 1) {
        printf("numbers[%d] = %d\n",
            index, numbers[index]);
    }

    //numbers points to the first element
    printf("*numbers = %d\n", *numbers);

    //remove old array from memory
    printf("\nfreeing old memory\n");
    free(numbers);

    //create new array in memory
    printf("using new memory\n");
    size = 7;
    numbers = (int*)malloc(size * sizeof(int));

    //create and print values
    for (index = 0; index < size; index += 1) {
        *(numbers + index) = 3 * index - 7;
        printf("numbers[%d] = %d\n", index,
            numbers[index]);
    } //a[b] == *(a + b)

    free(numbers); //free before exiting

    return wait_key();
}

//wait_key definition
int wait_key() {
    getchar();
    return 0;
}
output in prompt:
numbers[0] = 1
numbers[1] = 3
numbers[2] = 6
numbers[3] = 6
numbers[4] = 9
*numbers = 1

freeing old memory
using new memory
numbers[0] = -7
numbers[1] = -4
numbers[2] = -1
numbers[3] = 2
numbers[4] = 5
numbers[5] = 8
numbers[6] = 11

    This version of the numbers array allows you to create an array during any point in the program, but requires more maintenance.  Unfortunately, the size of this type of array cannot be calculated with the sizeof operation.  The sizeof operation will most likely return 4 or 8 which is the number of bytes required to point to a location in memory, not the number of bytes the data occupies.

    Also, the malloc and free commands must be used.  The malloc command is written as "(data type*)malloc(size * sizeof(data type))" where size is the number of elements and data type can be int, double, etc.  malloc checks for and fills available memory and returns a pointer to the first element.  This memory is not initialized though, so assigning values to each element is recommended.

    Once this memory is allocated with malloc, it remains in memory until free is called.  Using the same pointer malloc returns, free will remove an array and make its memory available for other uses.  If free is not called, the array can remain in memory until the computer is restarted.  It is recommended to compliment any malloc calls with a corresponding free call.

    For this example, the numbers array starts with five elements, but is later removed from memory.  Next, it is given seven new elements and finally removed from memory before the program stops.  Aside from malloc and free, the syntax is very similar to static arrays.  Notice that "*(numbers + index)" works similar to "numbers[index]"; this is because the pointer numbers points to the first element while numbers+1 points to the second element.  These written styles can be used interchangeably.

    Pointers can also be used for strings, which will be the next post.  Thank you for reading!