Last active
October 10, 2018 02:13
-
-
Save gubatron/9189e38886609e275627aeb0d0165f0f to your computer and use it in GitHub Desktop.
movePointer.cpp - on how arrays are passed to functions and how we can do something similar with pointers to them
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A short lesson on pointers and arrays in C++ | |
// Author: Angel Leon - October 9th 2018 | |
#include <iostream> | |
#include <string> | |
using namespace std; | |
int main() { | |
// define some string array with a few strings | |
string someArray[] = { "Nicole", "Leon", "Molina" }; | |
// get a pointer to the first element in the array | |
// (when you pass an array to a function, the function basically gets | |
// a pointer to the first element of the given array, passing an array | |
// does not copy the array to the function's stack memory region) | |
// in this code sample we're going to do what a function does when it receives | |
// a parameter, manually, and then we're going to move along the array by moving | |
// the pointer forward and reading what it's pointing to, | |
// instead of using the array's `[]` indexOf operator. | |
string *arrayPointer = (string*) &someArray; | |
// `&someArray` returns the memory address of the first element in the array | |
// '(string*)' casts that number into a string pointer, so we can assign it to `arrayPointer` | |
// let's print `arrayPointer` | |
cout << "arrayPointer -> " << arrayPointer << endl; // Prints something like -> 0x7ffee548d4a0, the memory address. | |
// if what I said is true, and we printed the memory address of `someArray[0]`, it should be the same | |
cout << "&someArray[0] -> " << &someArray[0] << endl; // Should print the same number as above -> 0x7ffee548d4a0 | |
// note, this number should change everytime you run the program, but it should be the same for those | |
// 2 prints above, this is because, your program doesn't always get the same memory available, | |
// the operating system is always managing memory for all the different processes. | |
// now let's print what's being pointed to (the first element), for this, we "de-reference" the pointer using the `*` operator | |
cout << "*arrayPointer -> " << *arrayPointer << endl; // Should print "Nicole" | |
// now let's move the pointer 1 position | |
// before we move though, let's write down the memory address, so we can do a little math later and we know | |
// how many bytes we're moving forward as we jump through the array | |
long firstMemoryAddress = (long) arrayPointer; | |
// let's print that, it should be the same as &someArray[0] too | |
cout << "firstMemoryAddress -> " << std::hex << firstMemoryAddress << endl; // Should print again -> 0x7ffee548d4a0 | |
// (std::hex is so that it prints it in hexadecimal, otherwise it prints the number in decimal) | |
arrayPointer++; // notice that we're adding 1, pointer arithmetic makes this easy, it does so knowing the byte count | |
// needed to move one position along the array, it knows so because it knows it's a pointer to string | |
// if it were a pointer to int, it would move automatically 4 bytes | |
// and let's print again | |
cout << "*arrayPointer -> " << *arrayPointer << endl; // Should print "Leon" | |
// Let's see the memory address now, should be different, should be the same as someArray[1]'s | |
cout << "arrayPointer -> " << arrayPointer << " - &someArray[1] -> " << &someArray[1] << endl; | |
// If we subtract the current memory address vs the first one, we'll know how many bytes the pointer | |
// is actually moving based on the pointer's type data size. | |
long memoryDelta = ((long) arrayPointer) - firstMemoryAddress; | |
cout << "memoryDelta -> " << memoryDelta << endl; // 18 bytes | |
// what's the size of the 'string' data type representation (not 'a string')? | |
cout << "sizeof(string) -> " << sizeof(string) << endl; // yup, 18 bytes | |
// 18 bytes because std::string is a class with members, functions and yes, a pointer to char* | |
// which is the actual string data, so your string array, is really an array of fancy pointers to char* along with some other things. | |
// if I were to implement the [i] operator for array in C++, I'd basically multiply the | |
// size in bytes of the array's data type, in our case `sizeof(string)` times the given index `i` | |
// and move in memory that byte-distance from the first element's memory position. | |
// This is a single operation and this is why you hear that array lookup (given an index) happens in constant time, | |
// no matterhow big the array is, it's a simple multiplication and addition, blazing fast lookup. | |
// hope this makes sense. | |
// now for fun, try moving the pointer 2 more times and see what happens :) | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment