Pointers

 

This page is about pointers in C. The C language has the ability to work with memory address locations - this is something that can be quite significant in embedded C.

Another use is in the manipulation of arrays, where it can be easier to work with the location of the array in memory, rather than always having to work with the array itself.

There are various ways to use pointers, at present this page is just about pointer variables.

 

Pointer variables

In the previous page about variables and constants, variables were described as a way of allocating a piece of memory for the storage of some data. The amount of memory allocated is dependent on the type of the variable.

In contrast, a pointer variable is a way of creating a memory location which stores the memory address of a variable, which stores the data.

By doing this, we can use the memory location of a piece of data in a function, instead of using the data itself.

Pointer variables are set up in just the same way as an ordinary variable, by declaring them before they are used.

Like ordinary variables, pointer variables have a type included in the declaration - this type needs to be the same as the type of the variable that the pointer variable is pointing to - this means that the compiler knows the type of the data that is contained in the specified memory location.

A pointer variable can be declared without specifying which variable it is pointing to - however the type must be given. In this example, a variable is set up, then a pointer variable is set up, and then the pointer variable is pointed to the first variable.


        signed long int var_1 = 100

        signed long int *ptr_var_1

        ptr_var_1 = &var_1

The first line sets up an signed long integer variable with an initial value of 100.

The second line sets up the pointer variable with the same type description - the star at the start of the variable name indicates that this is a pointer variable.

The third line points the pointer variable to the memory address of the first variable - the ampersand character indicates that it is the memory address of the first variable that the pointer variable should be equal to. Note that in this line, the * is not required - the pointer variable is named ptr_var_1, and that is how it is referred to.

Lines two and three can be combined, so that the pointer variable is given its content at the same time as the declaration.


        unsigned int var_1 = 100

        unsigned int *ptr_var_1 = &var_1

Just to be clear, the type declaration before the name of the pointer variable doesn`t define the type of the pointer variable - it defines the type of data that is in the variable that the pointer variable is - or will be - pointing to. Pointer variables themselves always contain an address, never any other kind of data, so they are effectively always unsigned integers. Whether they are 1 byte, 2 byte, or 4 byte, ie, short, int, or long, I think depends on both the hardware and the compiler, and on what they are pointing to.

The declaration of the pointer variable uses two operators, ie, the & character, and the * character. It is perhaps a bit of a confusion factor that C uses the same characters for several different purposes.

The & character is also used as a bitwise AND operator. In pointer variable declarations it is used to indicate the memory address of the object, rather than the object itself.

The * character is also used as a multiplication operator. In pointer variable declarations it is used to indicate that the variable being declared is a pointer variable.

Just to confuse things even more, there is another use of the * character, in association with pointer variables. As stated above, the name of the pointer variable is ptr_var_1, and that is the name that is used in functions, etc.

However if we write


        signed long int var_1 = 100

        signed long int *ptr_var_1

        ptr_var_1 = &var_1

        *ptr_var_1 = 101

then the * character in the fourth line is being used as an "indirection operator" - which means that instead of the pointer variable pointing to the address of the var_1 variable, it is now pointing to the content of the var_1 variable, and it changes the content of the var_1 to the value of 101.

It gets a bit more fun if we do multiplication of the contents of variable var_1, instead of addition, because we add another * character. Here is a script that compiles fine with gcc.


        #include <stdio.h>

        int var_1 = 100;                            //  declare the variable var_1

        int *ptr_var_1 = &var_1;                    //  declare the pointer variable

        int main()

           {

        printf(" \n \n \t %d \n " , var_1 );        //  content of variable var_1



        printf(" \n \t %p \n " , ptr_var_1 );       /*  content of pointer variable,
                                                     *  which contains the memory
                                                     *  address of the variable
                                                     *  var_1                    */


        *ptr_var_1 = *ptr_var_1 * 2;                /*  multiply the contents of 
                                                     *  variable var_1 by 2      */

        printf(" \n \t %d \n " , var_1 );           //  content of variable var_1 again


        *ptr_var_1*= 2;                             /*  multiply the contents of 
                                                     *  variable var_1 by 2 again, 
                                                     *  written in shorthand form  */

        printf(" \n \t %d \n " , var_1 );           //  content of variable var_1 again


        printf(" \n \t %p \n \n " , ptr_var_1 );    /*  content of pointer variable,
                                                     *  which contains the memory
                                                     *  address of the variable
                                                     *  var_1, which hasn`t changed
                                                     *  since last time              */

        return(0) ;

           }

When run, the programme produces the result of


        100

        0x804a014

        200

        400

        0x804a014

So we have changed the content of the original variable var-1, by working with the pointer variable, and the variable var_1 is still in the same memory location.

Moving on from changing the contents of the variable var_1, we can also use the pointer variable to change the memory address of the variable var_1. Because the pointer variable contains a number, just like any other number, we can do arithmetic on it, and this will change the memory address of the variable that the pointer variable is pointing to.

We do this by working on the pointer variable without using the leading indirection operator, the * character. Here is a short script that illustrates it.


        #include <stdio.h>

        int var_1 = 100;                            //  declare the variable var_1

        int *ptr_var_1 = &var_1;                    //  declare the pointer variable

        int main()

           {

        printf(" \n \n \t %d \n " , var_1 );        //  content of variable var_1

        printf(" \n \t %p \n " , ptr_var_1 );       /*  content of pointer variable,
                                                     *  which contains the memory
                                                     *  address of the variable
                                                     *  var_1                    */

        ptr_var_1 = ptr_var_1 + 1000;


        printf(" \n \t %d \n " , var_1 );           //  content of variable var_1 again

        printf(" \n \t %p \n \n " , ptr_var_1 );    /*  content of pointer variable,
                                                     *  which contains the new memory
                                                     *  address of the variable
                                                     *  var_1                    */

        return(0) ;

           }

After running the programme, we get the result


        100

        0x804a014

        100

        0x804afb4

So the original variable var_1 still contains the same content of 100, but the memory location of the variable has changed.

Out of curiosity, I tried to compile a script that declares the original variable as a constant variable, and then changes its value using the pointer variable. However it doesn`t compile, I just got error messages, so this isn`t a sneaky way to change constant variables.

 

Pointer arithmetic

Now we`ve seen that a pointer variable is a type of variable that contains a number - an unsigned integer - which number happens to be a memory location of another variable. We have also seen that we can do arithmetic with the content of a pointer variable, as shown above.

        
        ptr_var_1 = ptr_var_1 + 1000;
      

The memory location of the variable that ptr_var_1 is pointing to changed from 0x804a014 to 0x804afb4.

To make life a little easier, look at

        
        ptr_var_1 = ptr_var_1 + 1;
      

In other words we want to increment the memory location by 1.

So the simple result of this would be the memory location changes from 0x804a014 to 0x804a015 - ie, it has moved up one byte.

The variable var_1 has been declared as an integer, so occupies 2 bytes. So the memory location 0x804a015 actually contains half of the integer value in var_1, and isn`t free.

So we actually need to increment the memory location by 2 bytes, from 0x804a014 up to 0x804a016. Thereafter the variable var_1 will occupy 0x804a016 and 0x804a017.

So maybe we should write

        
        ptr_var_1 = ptr_var_1 + 2;
      

However most compilers will look and see how many bytes have been allocated to the variable var_1, and will move the variable up the memory by the correct amount of bytes.

A short integer will use just 1 byte, a normal integer will use 2 bytes, and a long integer will use 4 bytes.

This process is known as scaling, the programmer just needs to write

        
        ptr_var_1 = ptr_var_1 + 1;
      

and the compiler moves up the right number of bytes for the type of data being stored.

I haven`t seen any reference to this, but I assume that if a variable is declared


        char var_text[40] = some text string;

then the compiler will scale up the byte number by a factor of 40. However I don`t know.

 

This isn`t the end

There is quite a bit more to pointers than what I have on this page - other types of pointers include

The first two are going a bit deeper than where I want to go just now, and I have not covered structures and arrays yet, so there isn`t too much point in going down that road either.

So that`s the end of pointers for just now.

 

 

 

 

 

website design by ron-t

 

website hosting by freevirtualservers.com

 

© 2024   Ron Turner

 

+                                   +  

 

Link to the W3C website.   Link to the W3C website.