Friday, January 24, 2014

C++ and pointers...

Yay! Time for a totally programming related post, and a trip down memory lane.



Was reading an article the other day that basically ripped into modern computer science students for not being forced to learn C++ and pointers in a world where the norm is now languages like Java.




I did, to a very small degree, spend time learning C and C++ in university. But, when I graduated, I knew damn well I basically received a formal education in Java, but with a side of a crash course in those pesky things that came before. I then went on to be a C# guy, which is like Java on steroids in that it takes many things and makes them even more streamlined.



But, I still remembered that crash course in pointers. I'm still not sure if I agree necessarily with the conclusion that this is something that people in this field NEED to know. Or rather, whether or not you need it should depend on what specifically you plan to do within the field. This is certainly a great way to weed out those who just can't cut it. And, I remembering loving showing this stuff to people who thought they might have a knack for software development to scare them away.



So, I thought I would fire up a C++ project in Visual Studio, go find some examples and see if I could wrap my head around them. And about midway through , I found this example:



// more pointers

#include

using namespace std;



int main ()

int numbers[5];

int * p;

p = numbers; *p = 10;

p++; *p = 20;

p =*p = 30;

p = numbers + 3; *p = 40;

p = numbers; *(p+4) = 50;

for (int n=0; n", "5>; return 0;}



So, this little chunk of code would output: 10, 20, 30, 40, 50,



But, would I be able to sort out how? Absolutely. I swear, I have seen real code that reads this way, and it makes you think people just write code this way to mess with your mind. Pointers are actually VERY simple. With very few rules governing them.



The 2 things to note here that are different for arrays than primitives are that a pointer to an array actually references the first element in the array and arrays are ALWAYS composed of contiguous blocks of memory (at least virtually).



Thankfully, the site didn't actually cover this step by step, so you know I'm not cheating :)



So, line by line then:



INT NUMBERS[5];

This declaration allocates 5 contiguous blocks of memory for 5 integers. The actual values of the elements is currently not set.



INT * P;

This allocates a block of memory to a variable named p which is both an integer and a pointer to an integer :). The important note being that it is allocating memory to hold a pointer to an integer. All pointers are technically just integers regardless of the type they are referencing.



P = NUMBERS; *P = 10;

The p=numbers; merely assigns p the address of the array called numbers. Normally this would be p=but theis dereferencing that memory location which returns the value and assigns it the value of 10. If this weren't a training sample on pointers it would have simply been written thusly: numbers[0] = 10;



P++; *P = 20;

Prior to this line p contains the address of the first element of the numbers array. By incrementing it, we move it to the next address in memory. And, since we noted that arrays are contiguous blocks of memory, we know we are changing p from pointing to numbers[0] to numbers[1] which again is dereferenced and then set as 20.



P =*P = 30;

This time we are using to*P = 40;

As noted when we first assigned a value to p, numbers returns the address of the first element. Adding 3 will increment that pointer to 4th element in the array before assigning the value. Again, had we been incrementing all this time, we simply could have incremented p again, or, as per the last example we could have set p using p =. All of these approaches would get us to p containing the same address.



P = NUMBERS;*(P+4) = 50;

Really, at this point about the only thing interesting about this approach is that the address p is pointing at is set back to the location of numbers[0] and then we simply calculate the address of the 5th and final value in memory, dereference it and assign the value. Which really isn't all that exciting or interesting.



The remainder of the example is just printing out the result. But as you break it down line by line you can see how each line is just a different way of accessing a different memory location and assigning a value 10 higher than the last index contained.



And there you have it. After having not looked at a pointer in 10 years, I still understand how they work well enough to tackle an educational exercise. Maybe not much to brag about. But from that minimal knowledge, and taking the time to disassemble code a line at a time you should be able to tackle most problems related to pointers. If there are enough layers of them you'll probably need a few pots of coffee and heroic amounts of patience. But this topic which many deem to be one of the hardest is also fundamentally one of the simplest.



My experience with pointers has long been that most of the complexity actually comes flexibility/inconsistency in the syntax and consequently from that, inconsistent usage by developers. When people do as this example does and use pointers in multiple ways to accomplish the same thing, readability goes to the shitter. If all 5 array elements had been set consistently, regardless of which approach were used, most people would understand what the code was doing in a heart beat with only the most basic knowledge of pointers. And, if that model were followed consistently where applicable, most would be able to understand much more complex code.



So, feel free to weed out those that don't belong with pointers. But aren't regular expressions more fun for that? Just don't try and tell me that an understanding of them is in some way mandatory. If it were, languages like Java and C# which abstract them out of existence either wouldn't be able to function or wouldn't be comprehensible.
Full Post

No comments:

Post a Comment