/*************************************************************************** pointers.c ------------------- begin : Fri Mar 21 01:11:01 CST 2003 copyright : (C) 2003 by Andy Ruder email : aeruder@yahoo.com ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ /* Pointers Tutorial by Mr. Andy Ruder Section 1: Ok, here's the tutorial on pointers. Basically, pointers do exactly what they say they do : they point. The syntax for a pointer is just * . So, if you want a pointer to a integer, you just put int * int_variable; A pointer, basically, is just like any other type of variable, except you don't store values in it, you store memory locations. So, if you have a little program with int x; int * x_ptr; and you want to make x_ptr point to x, you do something similar to x_ptr = &x; When you put a & in front of a variable like that, you are telling the compiler that you don't want what x is storing, you want what the -=Memory Location=- of x is. But to fully understand how pointers work, you have to understand what exactly I mean by memory location. Memory can be described as just one long array of bytes or characters. _______________________________ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |___|___|___|___|___|___|___|___| Diagram of 8 bytes in memory. Now, each of those boxes above represents one byte or one memory location. Basically, 0-7 are the -memory locations- and each box or byte can store 8 bits or one character(a byte). Now, on a typical intel machine, a char type is 1 byte big, so it'll take up one of those memory boxes, and a int is 2 or 4 bytes big. Now, in reality, your program won't be using nice and neat memory locations like 0-7, if you print out what is stored in x_ptr above, it'll probably be something more like 0x4D32Ab12 or something similar. You may be wondering what exactly is good about pointers if all they can do is store memory locations. Well, you can change what is stored in the memory location that it points to. So, back to our original program. int x = 4; int *x_ptr = &x; printf("x_ptr = %ld\n", (long int) x_ptr); printf("&x = %ld\n", (long int) &x); printf("x = %d\n", x); printf("*x_ptr = %d\n", *x_ptr); Now, study that program, see how I found the value that is stored in the integer that x_ptr points to? I used *x_ptr to find the value of the int that it points to. I can also use similar syntax to change the value of what it points to. Add below to above program : *x_ptr = 125; printf("x = %d\n", x); printf("*x_ptr = %d\n", *x_ptr); I think you should find that *x_ptr changes the value of the integer it points to. By now, you may be wondering how to use pointers with arrays and if you aren't, you are now.(I am forcing you to) Section 2: Arrays Now, hopefully you know what arrays are(char buffer[300] is an array of 300 bytes.) Now, if you want to use pointers with arrays, it's the exact same syntax. char buffer[200]; // An array of 200 bytes char * pnt; pnt = buffer; // Or you COULD use // pnt = &buffer[0]; they are the same thing. So, now pnt points to the first byte. Before I go farther, I have to explain a little bit about arrays. _______________________________ | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |___|___|___|___|___|___|___|___| Diagram of 8 bytes in memory. Ok, here's the diagram again. If you have a char buffer[8] it takes exactly 8 bytes up in memory, and the memory that it takes up is straigt in a line; that is, if &char[0] == 0 then &char[1] == 1, and if &char[0] == 198 then &char[1] will equal 199. Its all a pretty simple concept. So, if we wanted to do something like change the 3rd byte to 'c' in the example above, we would only need to do something similar to this : char buffer[4]; // 4 bytes char *pnt; pnt = buffer; pnt[2] = 'c'; // OR, you could do something like pnt = &buffer[2] // followed by *pnt = 'c', but this way is the way // you will usually see it done That's all there really is to say about arrays and pointers Section 3: Structs Ok, hopefully you understand the basic principle of pointers by now, so I won't have to explain everything on this one. Ok, here's a struct: struct coordinate { int x; int y; }; Now, in a program, if we did something like struct coordinate point; We should be able to do something like point.x = 4; and point.y = 5; This all should sound familiar at least. But pointers to structs are a bit different. struct coordinate point; struct coordinate * point_ptr; point_ptr = &point; point.x = 4; point_ptr->y = 5; // Ah, since we use a pointer here we use the -> // operator instead of the . Ok, that's all I have to say about structs. Section 4: Added Notes. Like I said in the very first section, char usually takes up 1 byte while other types may take up more. Basically, if an int takes up 2 bytes, it works just like 2 characters put together. So really, you could do some screwy stuff like : int x[40]; char y[300]; char *char_ptr; int *int_ptr; int_ptr = x; // Or &x[0] char_ptr = y; char_ptr[30] = 'c'; int_ptr[20] = 100; // Now the screwy part char_ptr = (char *) x; // Ok, I'm FORCING x[0]'s memory location to // go into a char *, even though x[0] is an // INTEGER! char_ptr[20] = 'c'; Really, what this program demonstrates is that an array is an array and nothing more. An int array is just like a char array, it's still just a segment of memory, just that if you have an array of 30 ints and an array of 30 chars, the ints may actually take up 60 bytes or 120 bytes since ints are larger. And also, pointers can point to just about anything, including functions or, well, even pointers -- anything! Ok, now for the example program. */ #include #include #include int main(void) { char byte; char *byte_ptr; char byte_array[100]; int integer; int *int_ptr; int int_array[100]; printf("A char is %d byte(s).\n", sizeof(char)); // Sizeof returns the size // of a data type. printf("A int is %d byte(s).\n", sizeof(int)); printf("A char * takes up %d byte(s).\n", sizeof(char *)); printf("A int * takes up %d byte(s).\n\n", sizeof(int *)); byte = 100; integer = 124; byte_ptr = &byte; int_ptr = &integer; printf("byte = %d, integer = %d\n", byte, integer); printf("byte_ptr = %ld, int_ptr = %ld\n", (long int) byte_ptr, (long int) int_ptr); printf("&byte = %ld, &integer = %ld\n", (long int) &byte, (long int) &integer); printf("*byte_ptr = %d, *int_ptr = %d\n\n", *byte_ptr, *int_ptr); *byte_ptr = 5; *int_ptr = 100; printf("After *byte_ptr = 5 and *int_ptr = 100 : \n"); printf("byte = %d, integer = %d\n", (int) byte, integer); printf("byte_ptr = %ld, int_ptr = %ld\n", (long int) byte_ptr, (long int) int_ptr); printf("*byte_ptr = %d, *int_ptr = %d\n\n", (int) *byte_ptr, *int_ptr); byte_ptr = byte_array; printf("After byte_ptr = byte_array, byte_ptr = %ld\n", (long int) byte_ptr); byte_ptr = &byte_array[0]; printf("After byte_ptr = &byte_array[0], byte_ptr = %ld\n", (long int) byte_ptr); byte_ptr[12] = 5; printf("After byte_ptr[12] = 5, byte_array[12] = %d\n\n", (int) byte_array[12]); printf("Now, compare results as you look at the source code\nto the program!\n"); return 0; }