Workshops

Top  Previous  Next

I have decided to learn the C programming language many years ago; it all went smooth until I have reached the chapter that was dealing with pointers. 

I had a hard time trying to understand how these pointers work; I was so discouraged that I almost gave up programming. 

Therefore, I can only hope that you will make some sense out of these pointers by reading this month's article. 

 

So what are you waiting for? Go wash your face, shave your beard and then put on your brain warming hat - you are going to need it!

Well... actually, you might not need the hat (don't forget to shave, though) because my examples are very simple, as always.

 

#include <acknex.h>

#include <default.c>

 

STRING* value_str = "";

 

TEXT* value_txt =

{

       layer = 15;

       pos_x = 140;

       pos_y = 20;

       string(value_str);

       flags = VISIBLE;

 

function main()

{

       video_mode = 6; // create a program window of 640x480 pixels

       vec_set(screen_color, vector(55, 55, 55)); // make the background color dark

       

       int a, *p;

       a = 123;

       p = &a;

       str_for_num(value_str, *p);

}

 

See what I mean? You can't beat lite-C when it comes to efficient programming! This is the content of the pointers1.c file and here's the result of its run:

 

aum70_workshop1

 

The only lines that need our attention are listed below:

 

       int a, *p;

       a = 123;

       p = &a;

       str_for_num(value_str, *p);

 

The first line of code defines two integer variables: a regular variable named "a" and a C-style pointer named "p". 

 

Let's pretend that we don't know anything about GameStudio's pointers for now; we don't need that information anyway. A pointer is nothing more than a variable. 

But wait, it's a special variable! A pointer doesn't store values, like our regular "a" variable would do, but memory addresses for objects (variables, strings, tables, etc).

 

In our example, "a = 123;" sets the variable named a to 123. Nothing unusual until now, right? The following line, "p = &a;" assigns the address of a to the pointer named p. 

This means, in plain English or German, that if our variable named "a" will be stored in the computer's memory at the address 23443 (just an example), p will be set to 23443.

Here's a picture that explains more clearly what is happening.

 

aum70_workshop2

We can't predict the computer memory address where a certain variable will be stored, but a pointer can get it and keep track of it - isn't this a cool feature?

Here's the last line of code from pointers1.c that will be discussed:

 

str_for_num(value_str, *p);

 

We are using the * operator, which has nothing in common with the one that does the multiplication; both are using the same symbol, but have different functions.

The  * operator gives us the value that's stored in the memory location pointed by the pointer; since the content of the 23443rd memory cell is 123, *p will be equal to... 123, what else? The line of code converts 123 to a string that will be displayed on the screen; I have decided to use a simple text in order to display several numerical values without having to use lots of digits.

 

Starting to make some sense out of it? Here's a quick "how-to" guide: 

a) First of all, we need to tell our pointer which is the object that needs to be tracked (a variable, a table, etc). 

b) Then, we can use the  * operator to get the value that is stored at that address. However, we can do much more than this, as you will soon see.

 

The following example allows us to change the value of a variable using a pointer.

 

#include <acknex.h>

#include <default.c>

 

STRING* value_str = "";

 

TEXT* value_txt =

{

       layer = 15;

       pos_x = 140;

       pos_y = 20;

       string(value_str);

       flags = VISIBLE;

 

function main()

{

       video_mode = 6; // create a program window of 640x480 pixels

       vec_set(screen_color, vector(55, 55, 55)); // make the background color dark

       

       int a = 100, *p;

       p = &a;

       *p = 456;

       str_for_num(value_str, a);

}

 

These are the lines that need to be discussed:

 

       int a = 100, *p;

       p = &a;

       *p = 456;

       str_for_num(value_str, a); // display the new value of a

 

The first line defines an integer named "a" and sets its value to 100; we are also defining a pointer named p. Then, we tell our pointer to point to the address of "a".

The third line of code sets the value in the memory cell pointed by p to 456; believe it or not, a will change its value to 456 as well, because the value that was stored in its assigned memory cell has changed. The last line of code displays the new value of "a", showing us that the variable has changed its value indeed. Here's another picture that shows the entire process:

 

aum70_workshop3

 

Ready for more pointer-based action? Open the pointers3.c file.

 

#include <acknex.h>

#include <default.c>

 

STRING* value_str = "                                        "; // stores up to 40 characters

STRING* temp_str = "      "; // stores up to 6 characters

 

TEXT* values_txt =

{

       layer = 15;

       pos_x = 100;

       pos_y = 20;

       string (value_str);

       flags = VISIBLE;

}

 

int a[5];

 

function main()

{

       video_mode = 6; // create a program window of 640x480 pixels

       vec_set(screen_color, vector(55, 55, 55)); // make the background color dark

 

       int *p, i;

       str_cpy(value_str, "Table values: ");

       for (i = 0; i < 5; i++)

       {

               a[i] = i;

               str_for_num(temp_str, a[i]);

               str_cat(value_str, temp_str);

               str_cat(value_str, " ");

       }

       str_cat(value_str, "     Pointer values: ");

       p = a; // assign the starting address of the table named a to the pointer p

       for (i = 0; i < 5; i++)

       {

               str_for_num(temp_str, *(p + i));

               str_cat(value_str, temp_str);

               str_cat(value_str, " ");

       }                

}

 

The interesting stuff happens inside function main. First of all, we define a pointer named p and a variable named "i" that will be used as a counter. Then, we use a "for" loop to fill the array named "a" with numerical values: a[0] will be set to 0, a[1] will be set to 1 and so on. Each numerical value is then converted to a string and added to the big value_str string that will be displayed on the screen using values_txt.

 

At this point, we should see something like this on the screen:

 

aum70_workshop4

 

Here's the rest of the code, pasted below for your (and my) convenience:

 

       str_cat(value_str, "     Pointer values: ");

       p = a;

       for (i = 0; i < 5; i++)

       {

               str_for_num(temp_str, *(p + i));

               str_cat(value_str, temp_str);

               str_cat(value_str, " ");

       }                

 

The first line adds some text to the string that's displayed on the screen. The second line of code is the most important in this example: it assigns the starting address of the array named "a" to the pointer named "p". Yes, we can do this and we can then access and manipulate all the elements of the array (all the cells in a table, etc) using the pointer. Here's a picture that explains what is happening as soon as the "p = a;" line of code is run.

 

aum70_workshop5

The second "for" loop simply adds the values from the cells pointed by p... p+4 to our big string. Here's how the screen should look like:

 

aum70_workshop6

 

This proves the fact that our pointer mirrors (and has access to) all the array cells; something like "*(p + 2) = 333;" would change the value of a[2] to 333, get it?

 

Time to examine the last example; it's a snippet that showcases the real power of pointers:

 

#include <acknex.h>

#include <default.c>

 

STRING* text_str = "";

 

TEXT* commercial_txt =

{

       layer = 15;

       pos_x = 140;

       pos_y = 20;

       string(text_str);

       flags = VISIBLE;

}

 

function display_text(char *p)

{

       while (1)

       {

               while (*p)

               {

                       str_cpy(text_str, *p);

                       p++;

                       wait (-0.1);

               }

               p--;

               while (*p)

               {

                       str_cpy(text_str, *p);

                       p--;

                       wait (-0.1);

               }

               p++;

       }        

}

 

function main()

{

       video_mode = 6; // create a program window of 640x480 pixels

       vec_set(screen_color, vector(55, 55, 55)); // make the background color dark

       display_text(" This text will be scrolled back and forth on the screen! ");

}

 

The code scrolls back and forth a text on the screen, horizontally, just like some TV commercials do. Function main simply calls display_text( ) with the text that needs to be scrolled as an argument and display_text( ) does the rest.

 

function display_text(char *p)

{

       while (1)

       {

               while (*p)

               {

                       str_cpy(text_str, *p);

                       p++;

                       wait (-0.1);

               }

               p--;

               while (*p)

               {

                       str_cpy(text_str, *p);

                       p--;

                       wait (-0.1);

               }

               p++;

       }        

}

 

The function sets a pointer named p to the memory address that's used by the string that will be displayed. Let's take a closer look at the first "while (*p)" loop:

 

               while (*p)

               {

                       str_cpy(text_str, *p);

                       p++;

                       wait (-0.1);

               }

               p--;

 

The loop above will run for as long as the pointer doesn't reach the end of the string (the "null" character). We copy the object pointed by p to text_str, displaying it on the screen, and then we increment (we add 1 to) the pointer; this way, the engine will display less and less text. The loop will pause for 0.1 seconds in order to give us a decent (and not huge) scrolling speed; the motion will look like this on the screen:

 

This text will be scrolled back and forth on the screen!

his text will be scrolled back and forth on the screen!

is text will be scrolled back and forth on the screen!

s text will be scrolled back and forth on the screen!

text will be scrolled back and forth on the screen!

text will be scrolled back and forth on the screen!

ext will be scrolled back and forth on the screen!

xt will be scrolled back and forth on the screen!

t will be scrolled back and forth on the screen!

....................

screen!

creen!

reen!

een!

en!

n!

!

 

The first while (*p) loop has stopped now - the pointer has reached the end of the string. We use a "p--;" instruction because we want the pointer to move a memory cell backwards, until it encounters the last useful character in the string (not the "null"!). A similar loop follows, decrementing the pointer and thus displaying more and more characters from our string on the screen.

 

!

n!

en!

een!

reen!

creen!

screen!

....................

t will be scrolled back and forth on the screen!

xt will be scrolled back and forth on the screen!

ext will be scrolled back and forth on the screen!

text will be scrolled back and forth on the screen!

text will be scrolled back and forth on the screen!

s text will be scrolled back and forth on the screen!

is text will be scrolled back and forth on the screen!

his text will be scrolled back and forth on the screen!

This text will be scrolled back and forth on the screen!

 

The big "while (1)" loop makes sure that the text is scrolled back and forth at all times. We could have done the same thing using str_clip and str_trunc, but the number of lines of code would have been much bigger and the application would have run slower. As a general rule, working with pointers will always lead to faster running code.

 

This concludes our pointer introduction. I hope that you aren't scared of pointers anymore because (and I know this from a trusty source) they are now very afraid of you...