In this small article, I show you about pointers by performing the same task using pointers in 3 different way. I think for some one learning c++ this is a very good approach because you can see pointers from different angles and get a much better idea as to what they and how to use them.
the code uses 3 different approaches using pointers to create an array of strings. you can look at the it as a sparse matrix of characters or just an array of strings like
Aa01234
Bb012
Cc0123456
etc.
the 3 approaches are offset, indexes and increments
the codes uses the #define in order to be able to compile
easily the each aproach so by just commenting these 3 lines
you can see how each approach works.
for example now it is set to run using increments
1 2 3
|
//#define _use_offset_
//#define _use_array_
#define _use_increments_
|
the data structure I use is the char**
this is a pointer to a pointer to a character
like -> (-> character)
I initialize it to
|
char** array_of_strings = new char*[26];
|
so is basically an array of strings like
-> ->sssssssssssss
->sssssssssssss
->sssssssssssss
array_of_stringsis the main pointer -> which we move by either method
vertically (is better to think of it this way). at the moment
we dereference *array_of_strings we then have another pointer the one that
points to the actual string, the second -> above.
so array_of_strings++ moves to the next string (vertical) and
(*array_of_strings)++ points to the next character in the string horizontal.
the first approach using offsets, in this approach we don't modify
the pointers, instead we use some offset value to point to the data
like *(pointer+5) = something. because pointers hold address we can so this
so pointer+5 points to the address of the byte which is 5 bytes from pointer
in array terminology as you will see in the array approach this is equivalent to pointer[5]. In increments terminology this is equivalent to
++pointer;++pointer;++pointer;++pointer;++pointer, incrementing the pointer 5
times.
the second approach is the best and easiest, using array indexes
array[i][j].
the third approach is the increments. here we need to modify the pointer
because we move the pointer forward or backward using the ++ and -- operators.
so p[1], *(p+1) and *++p are 3 ways to do the same thing
point pointer to one byte after pointer.
in the increment method you will see i used 2 pointers
array_of_strings and new_string they are both pointers but they
behave differently. array_of_strings is a pointer to a pointer
it points to a pointer to a byte (character), while new_string
points to the actual data the string. when we do array_of_strings++
we move array_of_strings to point to the next string.
Aa01234
*array_of_strings++ -> Bb01234567
and when we do *++new_string we point to the next character in the string
Aa01234
^
|
*++new_pointer
notice i use the increment operator before *++p not *p++ because i wanted
to increment p first and then dereference. if i had done *p++ it would process
Aa012345 or which ever string twice
bellow is the code, it has comments and I think is not hard to follow
just comment two of the #define and leave the one you want to experiment with
uncommented, then set break points and see how it works.
to run the code just create a new windows console application if using
Microsoft visual studio. if using some other tool then just copy paste
the code in your Main function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
/************************************************************************/
/*
this example shows the equivalence in pointer math between
array p[i]
offset *(p+i)
increment p++ p++ ..... i number of times
example p[3] = *(p+3) = p++ p++ p++
*/
//#define _use_offset_
//#define _use_array_
#define _use_increments_
#ifdef _use_offset_
cout << "using offset\n";
#endif
#ifdef _use_array_
cout << "using array\n";
#endif
#ifdef _use_increments_
cout << "using increments\n";
#endif
int j;
/*
declare and initialize the sparse matrix of characters
or the array of string, whichever fits.
*/
char** array_of_strings = new char*[26];
for (int i = 0; i < 26 ; i++)
{
#ifdef _use_offset_
/*
using offsets
instead of changing the pointer, just use
and offset from it all the time. the i is the
vertical offset into the table of strings
while the j is the horizontal. j = x and y = i
in vector terminology.
*/
*(array_of_strings+i) = new char(toascii(65+i));
*(*(array_of_strings+i)+1) = char(toascii(97+i));
for (j = 2; j < rand() % 16 + 2; j++)
*(*(array_of_strings+i)+j) = char(toascii(48+j-2));
*(*(array_of_strings+i)+j) = '\0';
#endif
#ifdef _use_array_
/*
using arrays
the simplest and prefered way because is more
readable and cleaner. just use array indexes
[y][x] or [i][j]
*/
array_of_strings[i] = new char(toascii(65+i));
array_of_strings[i][1] = char(toascii(97+i));
for (j = 2; j < rand() % 16 + 2; j++)
array_of_strings[i][j] = char(toascii(48+j-2));
array_of_strings[i][j] = '\0';
#endif
#ifdef _use_increments_
/*
use increments
here we change the pointers instead of using offsets
like p+i we actuaqlly increment the pointers p++
two things we need a two pointers the vertical pointer
and the horizontal pointer which actually points to
each string. array_of_strings is the verticaal and
new_string is the horizontal and the one which
points to the string and we use to modify the strings.
before printing out the strings we need to reset
the vertical pointer array_of_strings back to the
to the beginning so we simply subtract 26 from it
because we incremented it 26 times.
*/
char* new_string = *array_of_strings++ = new char(toascii(65+i));
*++new_string = char(toascii(97+i));
for (j = 2; j < rand() % 16 + 2; j++)
*++new_string = char(toascii(48+j-2));
*++new_string = '\0';
#endif
}
#ifdef _use_increments_
array_of_strings = array_of_strings - 26;
#endif
for (int i = 0; i < 26 ; i++)
{
#ifdef _use_offset_
cout << *(array_of_strings+i) << endl;
#endif
#ifdef _use_array_
cout << array_of_strings[i] << endl;
#endif
#ifdef _use_increments_
cout << *array_of_strings++ << endl;
#endif
}
/************************************************************************/
|