Tutorial seven. About pointers and strings

This is the seventh tutorial in the series Online C Tutorial for beginners and is about pointers and strings. These are single page bite size tutorials which can usually be run on either codepad.org or ideone.com.

A C String is a Pointer

It’s actually a pointer to an array of chars. However unlike normal arrays where the size is predetermined, you can have a pointer point to any size of string so long as it finishes with a 0 character.

The string itself is stored somewhere in memory, an array of characters with a terminating null. The char * variable holds the address of the location where first character in the string is stored and the remaining characters follow. So for this declaration.


char * fred="FRED";

If fred is at location 5000 in memory and the FRED characters are at location 8000 then the memory and contents will look something like this. Don’t forget the ASCII code for A is 65, B is 66 etc (all values in decimal).


5000: 8000  /* pointer to 8000 */
...
8000: 70 /* 'F' */
8001: 82 /* 'R' */
8002: 69 /* 'E' */
8003: 68 /* 'D' */
8004: 0 /* NULL

I’ve shown the values in decimal just to make it clearer. If you are looking at memory in a debugger you’d usually see the hexadecimal values and text. So it would look a bit like this with the decimal values above in hexadecimal below.


1388: 40 1f .....  /* 8000 decimal = 1f40 in hexadecimal */
...
1F40: 46 52 45 44 00 ...... FRED....

The hexadecimal of 500010 in base 16 is 138816 and 800010 is 1F4016.

Here is a more detailed example to give a better flavour of strings (aka char *). If you remember from the previous tutorial, char * means a pointer to a char. To make the program more readable, I’ve used typedef to give a name to char * which is string. This can be viewed and run online at Ideone.com.

I find that hiding pointers with a typedef can make the program much more readable. Feel free to use char * though if you prefer that.

#include <stdio.h>
#include  <stdlib.h> /* meded for malloc */ 
typedef char *string; 
int main(int argc, char* argv[]) 
{ 
    string name="David"; 
    string noname; 
    string longname="a very long name"; 
    noname=(string)malloc(5000) ; 
    noname[0]='M'; 
    noname[1]='Y'; 
    noname[2]='
#include <stdio.h>
#include  <stdlib.h> /* meded for malloc */ 
typedef char *string; 
int main(int argc, char* argv[]) 
{ 
string name="David"; 
string noname; 
string longname="a very long name"; 
noname=(string)malloc(5000) ; 
noname[0]='M'; 
noname[1]='Y'; 
noname[2]='\0'; 
printf("%s name is %s not a %s",noname,name,longname) ; 
free(noname) ; 
return 0; 
}
'; printf("%s name is %s not a %s",noname,name,longname) ; free(noname) ; return 0; }

The first line inside main declares a string variable called name and initializes it to David. This actually allocates 6 bytes to hold the string, five for the letters David and one for the null (byte value 0) which terminates the string. The compiler adds the null automatically for text declared like this but in a few cases other cases you have to add it. Note you can use ‘\0’ or 0 or NULL. All three work.

The string noname is declared but not initialized yet. You should never read or write to an uninitialized variable as it may point anywhere. The most likely thing that will happen if you do is that it will crash.

To use noname, we must manually allocate memory; the malloc() function call allocates a rather excessive 5000 bytes for it. The malloc() function call is defined in stdlib.h so we must include that at the start and stdio.h for the printf.

Note that malloc() returns a void * which means a raw pointer to no specific type. To assign this to noname, it has to be cast to a string hence the (string). You always have to cast malloc() calls.

noname=(string)malloc(5000) ;

Having allocated the memory and assigned the pointer to the memory to noname, we now have a pointer to a block of ram 5000 bytes in size. But (a) it’s not initialized and (b) certainly has no null at the end end  so if we tried to printf(noname) it would not go well (again most likely a crash).

I’ve manually assigned a short string, the word “MY” character by character in two assignments and then a third assignment of ‘\0’ to terminate it. Finally to prove that all three strings are valid, I’ve called printf() to output them and this is what you get. Yes the a a is deliberate…

MY name is David not a a very long name

For every malloc there’s a free

Although in a short program like this forgetting to free any memory allocated by the malloc won’t do much harm, it’s a good habit to get into that every malloc() is matched by a free(). The free(noname) knows from the pointer noname how big it is and where the allocated ram is located so that’s all that’s needed.

Generally you should to try to match memory allocation and freeing up or you’ll just introduce memory leaks and tracking those down can be very tedious.

We’ll return to strings in the future but in the next C pointer tutorial, I’ll show how we can use pointers to build complex data structures.

Link to previous tutorial.

Link to next tutorial,

(Visited 32 times, 1 visits today)