Gerard-Meier

Pointers!

Mar 3rd, 2011
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.58 KB | None | 0 0
  1. /*
  2.  * Simple program to demonstrate a couple uses for pointers. This program was
  3.  * written so I could learn more about how to apply pointers and their syntax.
  4.  * As I'm a C novice, please don't just take this file for granted as it may
  5.  * contain errors and or bad practises.
  6.  *
  7.  * By Gerard (gerjo) Meier
  8.  */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <assert.h>
  12.  
  13. // Some function prototypes as we're using a "One-pass compiler":
  14. void pointersAndArrays(void);
  15. void referencesAndVariables(void);
  16. void referencesAndStructs(void);
  17. void testingArrays(void);
  18. void pointerToStruct(void);
  19. void pointerToFunction(void);
  20. void pointerToFunctionInStruct(void);
  21.  
  22. int  multiply(int a, int b);
  23. int  add(int a, int b);
  24. int* getArray1();
  25. int* getArray2();
  26. int* getArray3();
  27.  
  28. // Point of entry:
  29. int main(int argc, char *argv[]) {
  30.    
  31.     printf("Testing pointers and arrays: \n --------------------\n");
  32.     pointersAndArrays();
  33.    
  34.     printf("\n\n\nTesting references and variables: \n --------------------\n");
  35.     referencesAndVariables();
  36.    
  37.     printf("\n\n\nTesting references and structs: \n --------------------\n");
  38.     referencesAndStructs();
  39.    
  40.     printf("\n\n\nTesting Arrays: \n --------------------\n");
  41.     testingArrays();
  42.    
  43.     printf("\n\n\nTesting Pointers to Structs: \n --------------------\n");
  44.     pointerToStruct();
  45.    
  46.     printf("\n\n\nTesting Pointers to functions: \n --------------------\n");
  47.     pointerToFunction();
  48.    
  49.     printf("\n\n\nTesting Pointers to functions within structs (fake classes?): \n --------------------\n");
  50.     pointerToFunctionInStruct();
  51.    
  52.     system("PAUSE");   
  53.     return 0;
  54. }
  55.  
  56. // Demonstrate that an array is nothing more than a bunch of memory "blocks" in a row.
  57. void pointersAndArrays(void) {
  58.     int i;
  59.     int array[] = {0,1,2,3,4,5,6,7,8,9};
  60.     int *pointerToArray;
  61.    
  62.     pointerToArray = array; // Notice the lacking &, which apparently has to be ommitted when using arrays.
  63.    
  64.    
  65.     for(i = 0; i < 10; ++i) {
  66.         // Using an index is the same as incrementing the pointer address. (unsure how "safe" this actually is)
  67.         assert(array[i] == *(pointerToArray + i));
  68.        
  69.         printf("Values:(%i == %i)  Addresses:(%i == %i)\n", array[i], *(pointerToArray + i), &array[i], (pointerToArray + i));
  70.     }
  71. }
  72.  
  73. // Reference two variables to hold the same "value"
  74. void referencesAndVariables(void) {
  75.     int value;
  76.     int *pointerToValue;
  77.    
  78.     value            = 100;
  79.     pointerToValue   = &value;
  80.     value            = 99;
  81.    
  82.     // The address of value is the same as pointerToValue!
  83.     assert(&value == pointerToValue);
  84.     printf("%i == %i\n", &value, pointerToValue);
  85.    
  86.     // The values are the same, too.
  87.     assert(value == *pointerToValue);
  88.     printf("%i == %i\n", value, *pointerToValue);
  89. }
  90.  
  91. // Reference a variable with in a struct:
  92. void referencesAndStructs(void) {
  93.  
  94.     int value;      // Some value that we'll be playing with.
  95.     struct Wrapper; // Forward declaration.
  96.  
  97.     // Create some structure:
  98.     struct Wrapper {
  99.         int *pointerToValue;      
  100.     } foo;
  101.    
  102.     // "link" the pointer to the actual int:
  103.     foo.pointerToValue = &value; // The & makes sure we retrieve the memory address, not the memory value.
  104.                                  // notice the lacking * as we're setting the actual memory address, not memory value.
  105.    
  106.     // Assign some values to both variables:
  107.     *foo.pointerToValue = 102;  // Notice the * is used this time to access the actual memory value, and not the memory address.
  108.     value = 78;                 // Set the original variable.
  109.    
  110.     // Variables hold the same data!
  111.     assert(value == *foo.pointerToValue);
  112.     printf("%i == %i\n", value, *foo.pointerToValue);
  113. }
  114.  
  115.  // This is how it should NOT be done. It will "probably" compile just fine,
  116.  // and "may" execute too, if you're "lucky".
  117. int* getArray1(void) {
  118.     int array[] = {0,1,2,3,4,5,6,7,8,9}; // Privately allocated array.
  119.    
  120.     // Return a pointer to a privately allocated array is not "allowed":
  121.     return array; // Will mostlikely yield a compiler "warning", not an "error".
  122. }
  123.  
  124. // This is the right idea, however, sooner or later we might cause a buffer
  125. // overflow and override some vital part in the memory. The memory I believe is also
  126. // privately "allocated".
  127. // In short: This is NOT how it should be done.
  128. int* getArray2(void) {
  129.     int *array;
  130.     int i;
  131.      
  132.     // We just "assume" that the next 9 memory blocks are free, while this will
  133.     // probably "work" most of the time, it's best to first actually allocate the
  134.     // memory (as seen in the next function)
  135.     for(i = 0; i < 10; ++i) array[i] = i;
  136.    
  137.     return array;
  138. }
  139.  
  140. // This is how it should be done. Much like the C++ new keyword, the
  141. // memory has to be released after use via the "free(*pointer)" function. (called delete/delete[] in C++)
  142. int* getArray3(void) {
  143.     int *array = (int*)malloc(10 * sizeof (int));  // Dynamically allocate memory (array)
  144.     int i;
  145.    
  146.     if(array == NULL) abort();// The computer ran out of memory? Probably want to abort the program here.
  147.    
  148.     // Fill the array:
  149.     for(i = 0; i < 10; ++i) array[i] = i;
  150.    
  151.     // Do not forget to eventually release the memory, too!
  152.     return array;
  153. }
  154.  
  155. void testingArrays(void) {
  156.     //int* array1 = getArray1(); // This will probably crash the application, or otherwise cause unexpected behavior.
  157.     //int* array2 = getArray2(); // This will probably crash the application, or otherwise cause unexpected behavior.
  158.     int* array3 = getArray3();   // The only correct function to return an int[10] array
  159.     int i;
  160.    
  161.     for(i = 0; i < 10; ++i) {
  162.         assert(i == array3[i]);  
  163.        
  164.         // Notice how variable i remains at the same memory address!
  165.         printf("Values:(%i == %i)  Addresses:(%i != %i)\n", i, array3[i], &i, &array3[i]);
  166.  
  167.     }
  168.    
  169.     // No memory leak in this awesome application!
  170.     free(array3);
  171. }
  172.  
  173. void pointerToStruct(void) {
  174.     // Define some basic structure:
  175.     struct someStruct {
  176.         int a;
  177.     } myStruct;
  178.    
  179.     //struct someStruct myStruct;
  180.     struct someStruct *pointerToStruct;
  181.    
  182.     pointerToStruct     = &myStruct; // Point the pointer towards the actual struct instance.
  183.     pointerToStruct->a  = 101; // Set "a" via the pointer. (notice the -> instead of .)
  184.     myStruct.a          = 102; // or set "a" directly. (notice the . instead of ->)
  185.    
  186.     assert(myStruct.a == pointerToStruct->a);
  187.     printf("%i == %i\n", myStruct.a, pointerToStruct->a);
  188. }
  189.  
  190.  
  191. int multiply(int a, int b) {
  192.     return a * b;  
  193. }
  194.  
  195. int add(int a, int b) {
  196.     return a + b;  
  197. }
  198.  
  199. void pointerToFunction(void) {
  200.     // pointer to function, notice how the return types and arguments are definend.
  201.     int (*pointerToFunction) (int, int) = &multiply;
  202.    
  203.     assert(multiply(3, 3) == pointerToFunction(3, 3));
  204.     //printf("%i == %i\n", multiply(3, 3), pointerToFunction(3, 3));
  205.     printf("Values:(%i == %i)  Addresses:(%i == %i)\n", multiply(3, 3), pointerToFunction(3, 3), &multiply, pointerToFunction);
  206. }
  207.  
  208. // Fancy that! functions in a struct:
  209. void pointerToFunctionInStruct(void) {
  210.     // A simple wrapper struct for some "math" tools:
  211.     struct MathTools {
  212.         int (*multiply) (int, int);
  213.         int (*add) (int, int);
  214.     } tools;
  215.  
  216.     // Point the pointers towards the functions:
  217.     tools.multiply = &multiply;
  218.     tools.add      = &add;
  219.    
  220.     // Assertions:
  221.     assert(tools.multiply(3, 3) == tools.add(6, 3));
  222.     printf("%i %i\n", tools.multiply(3, 3), tools.add(6, 3));
  223. }
Advertisement
Add Comment
Please, Sign In to add comment