Dr4gs Introduction To C - Chapter 5 :: Pointers http://dynamichell.com - Computer Security/Programming Group ========================= Chapter 5 :: Pointers ========================= Hey just want to say thanks for reading the tutorial! I would like to start by asking you - what is a pointer? im sure you’ve herd of it but it seems a bit scary!, have no fear, i am sure by the end of this tutorial you will know pointers like the back of your own Ass (excuse the french). So what is a pointer? It is one of those things that beginners find it hard to grasp the concept of. The purpose of this tutorial, is to provide a short introduction to pointers in C, and their different uses and advantages. Some people find it that the main reason having problems with pointers is that they have a weak understanding for variables( as they are used in C) Thus we begin with a discussion in C Variables. A variable in a program is something with a name, which the value can change. The way in which the linker handler assigns this, is that it allocates a space in memory, for that type of variable(to hold the value of it). The size of the allocated memory depends on the range, in which the variable is allowed to change/vary. Example: On a 32Bit machine, the size of an integer variable is 4 bytes. Also on older 16Bit machines, integer types were a size of only 2 bytes. However, the size of a variable in C, does not need to be machine specific. Also, there are many other types of integers in C(long and short integers) For the rest of this tutorial, the code is based on a 32Bit Architecture. So if we want to know the SIZE of a variable, we would use the sizeof() operator. Due to the parenthesis on sizeof, you may think it is a function, however no, it is an operator. Here is the code you would need to use sizeof() =============================================== #include int main() { printf("The Size Of a Short On Your System Is: %d \n", sizeof(short)); printf("The Size Of an Int On Your System Is: %d \n", sizeof(int)); printf("The Size Of a Float On Your System Is: %d \n", sizeof(float)); printf("The Size Of a Long On Your System Is: %d \n", sizeof(long)); } The above code would identify for you, the sizes of the variables used, on your computer system. So anyway i hope you understand the concept of the sizeof operator (to find the size of a variables data type(how many bytes it sets aside)). ======================== A Pointer ======================== A pointer is like a variable, however, it doesn’t hold a value, it holds the address of another storage location in memory. Each storage location is like a 'box' in memory(a grid of boxes) also known as a matrix. As we are dealing with x86(32Bit) The address can vary from 0x00000000 - 0xFFFFFFFF Assume we have an int called i. It holds a value, undefined as of yet. Also, Its address would be represented by the symbol & (&i) However, if a pointer is to be used to point to a variable, it should be stored like the following. ========================== int i; /* i's type is int. */ int *z; /* this is a pointer(z), pointing to an int: int-pointer */ int *z = &i; /* This is a pointer(z), pointing to the address of i */ ========================== The * is the symbol for a pointer, for z, and the & symbol returns the address of the argument(i). If you are still a bit hazy on the concept of pointers, here is a diagram to help you. (its a little plain :P) ====================== ======================= = Address: 4000 = = Address: 5000 = = Value: 5000 = ---------> = Value: 25 = = Name: z, a pointer = = Name: x, a variable = = to an int(x) = = thats an int = ====================== ======================= Examples: If we want to change the address of a pointer. We could not do the following. z = 5000; We would have to do the following. *z = 5000; Remember that all variables bus be declared, so we must previously do: int *z; Which would then point to x. After we have given our pointer an address to point to, we can see the exact memory location that your pointed-to variable is stored. printf("The Value of z is %d \n", *y); Output: ======= The Value of z is 0xFE584C4 However, if we did not set our pointer to point anywhere, the output would be: The Value of z is 0x0 Note: Remember is previous chapters, we have talked about 'scanf' , and we did not go into detail about the & operator. Well now having learned a little more about C, we can give the following explanation. With the syntax: scanf("%d",z); - we could expect that scanf reads a pointer to a variable, not a variable. In this function, we want scanf to go into z, so we must tell scanf the address of where z lies. Thus, the &(address of) operator, used in &i. Tells scanf where z lies. ============================ Arrays and Pointers ============================ Normally we create an array like so; int number[10]; And knowing that we can access individual indexes in the array, like number[5]. We can now know that without specifying the array index; number[]. The array is now actually a pointer, pointing to the starting location of the array / to the first index in the array number[0]. So this is all well and good, but you may still be thinking; what is so good about pointers? why would we not just create a variable and use that directly. The answer is. Well we know that functions pass arguments(parameters), and arguments return, return values. However, There are limits and boundaries(scope) to what we can perform with using direct variables, and pointers avoid this problem. Here is an example, of a program that is out of 'scope'. ================================= /* Program Name: dhell.c */ #include int myfunction(int x); int main() { int z = 0; myfunction(z); printf("z = %d \n", z); } int myfunction(int x) { z = 10; } ================================== Now if we compile this; Linux: gcc dhell.c -o dhell And Then Do ./dhell We will get errors in out program, stating that z is undeclared. But wait a minute, didn’t we declare z within main? Yes we did, but when assigning the value 10 to z in 'myfunction', z was undeclared within myfunction. This is a result of scope, and z is out, wayyy out :) ================================== The Use of pointers :) ================================== Now if we created the same program, however using pointers, this problem with scope can be avoided. /* Program Name: dhell.c */ #include int myfunction(int *x); int main() { int z = 0; myfunction(&z); printf("z = %d \n", z); } int myfunction(int *x) { *x = 10; } This will compile and run successfully, by the use of pointers, now to explain it. The main difference in these examples, is the prototype for 'my function'. It is still an int type function, but its argument is no longer z, it is a pointer called x. Thus, when using myfunction(&z); - the argument being passed is *x. However, when using &z, it is now expecting a pointer to an integer, in order for this to run, we must state the address that our pointer(being passed), is pointing to. ============================ Arrays and Pointers (Continued) ============================ As i have covered in the previous section about arrays. If we do not specify a location to relate to in the array, it will refer to the first index of the array[0]; Normal Arrays are declared like so: char my_array[30] = "Drag"; We could also declare the same array as the following: char my_array[] = "Drag"; This array will create room for the 4 characters specified, and one element for the null character ("\0") When using char arrays (strings) we must have some way to keep track of the amount of elements in the array. However, some functions will break up strings into sections called (substrings) Or even replacing certain parts of strings with others. Thus, there must be a valid way of defining the size of a current string stored by the array of characters. In C, chars are entered into elements of the array and then terminated by the NULL character. The above code ( my_array[] = "Drag"; ) is actually stored like so: ====================================================== char my_array[] = "Drag"; Thus being stored like this; my_array[0] = "D"; my_array[1] = "r"; my_array[2] = "a"; my_array[3] = "g"; my_array[4] = "\0"; ======================================================= The ASCII value of NULL is 0, which is defined in stdio.h; this is used so we can refer to NULL rather than referring to expressions. Elements in the array after NULL, are regarded as garbage and are ignored. When the string is passed in, it will start at an index of 0 and following characters are obtained by incrementing the index value, until the first NULL character is reached. Signaling the "end of string". A Short example for using NULL characters, and in this case, validating for them. ======================================================== #include int i = 0; char my_array[]; int main() { while (my_array[i] != '\0') { putchar(my_array[i]); i++; printf("\n"); } } ======================================================== This program is pretty straight forward. It is a validation 'while' loop, checking that the array, is not at its end element (the NULL character"\0") Then takes in the value of my_array at the current element 'i'. Increments 'i' by one (i++) Prints a new line (\n); The above example can also be written as follow: From: my_array[i] != '\0'; To: my_array[i] != NULL; or To: my_array[i] != 0; ======================================================== Aright - This concludes my chapter 5 Tutorial on C Pointers. Chapter 4 is 3/4 Created, however on an un-accessible HDD right now. Chapter 4 :: File I/O will be released ASAP, if i don’t re-create it again. Some books have pointers before file i/o, so it will not be that big a setback in you(the readers) case. Thanks For Reading My Tutorials, i Hope u Had as Much Fun Reading Them, As i Did Writing Them :o)