Pointer notation is confusing.

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Pointer notation is confusing.

      Not only is their use sorely demonstrated in the book I'm reading, but the notation is even more confusing. So yeah they reference to a variables location in memory, with that you can pass by reference to a function to allow the value to be change outside of it's normal scope.

      I'm catching up on some of the things that I struggled with, Pointers are the first on the list..
      You may call me char 71 97 100 100 97 109.
    • Hey Gaddam,

      Pointers refer to a memory location, which is usually somewhere on the heap. Any time you declare a variable that doesn't use dynamic allocation (aka "new", "malloc", etc.), it is being stored on the stack inside the current scope.

      Generally you use pointers to refer to things on the heap because they are outside of any scope. In other words, if you declare a variable on the heap in one function, you can safely use it somewhere else. The alternative would be constantly copying the memory around to ensure that it's accessible at every scope.

      When you declare a variable on the stack, as you leave its scope, it gets freed as the stack is unwound. So in regards to changing something outside of it's normal scope, if you mean changing a value after it's left that scope, that's a bad idea:

      Source Code

      1. void foo()
      2. {
      3. int* pointer = nullptr;
      4. // Nested scope.
      5. {
      6. int i =7;
      7. pointer = &i;
      8. }
      9. *pointer = 10; // Bad, bad, bad, don't do this!
      10. }


      However you can safely use pointers/by reference to do "out" variables. This is because when you call a function, you're continuing to wind up the stack, so in the above example, if the inner scope called "bar(&i)", that would be valid because the variable "i" doesn't unwind till the next line.

      If you've ever used a higher level language like C# or Java, everything that's a "reference type" (classes), not a "value type" (int, char, bool, etc.), is basically just a pointer. The difference is you can't manipulate the address that it's pointing at, only the memory at that address.

      GCC covers some pointer tips, like using shared_ptr, which will hopefully save you some headaches and help you write better code.

      Sorry if a bunch of that comes off as gibberish, but I'll happily try to give more info or answer any specific questions you have about pointers, if that helps :)

      Cheers,
      James
    • Thanks Rick,

      I think the issue is that the book only gives you a two page lesson on pointers and then expects you to make some programs using them. It is an introductory book also so it's written for beginners.. but it is quite fast paced in terms of what you are expected to learn by the end of the chapter to perform the exercises!

      Source Code

      1. (*(*(coffee+ i)) + j)


      coffee[j] - this is easy to read for me

      The above is the pointer notation which is the equivalent to the statement above.

      Do you read this starting at the outside () then proceed inward because it's the order of operation? To me it looks like it's dereferencing i and j, appending the value to coffee to be accessed?

      I know of the Heap and the Free Store so that actually makes sense, in my mind pointers are good to use to avoid duplication, and to optimize performance.

      I've been trying to get this into my head so I can fully utilize pointers all around, so far in my mind they are like a global variable but not quite identical, in that they can be used anywhere within the program no matter the scope of where they are declared, so long as they are included from a base class.. etc..?

      I do appreciate your time and for giving me some 'pointers' :)
      You may call me char 71 97 100 100 97 109.
    • kaykry Thanks!

      Yes that trap was mentioned so I noted it down, as for the under the hood stuff.. yeah that's a bit to chew down lol!

      I'm using VS2010 so I'm taking advantage of the:

      ptr(nullptr); :)

      That's really the easy part to grasp is initializing and assigning an address to the pointer for use, the hard part is what in the bloody heck am I to do with them.. the book is showing them in place of arrays so I'll have a look into that further, it also said you can use them to work with arrays but so far I haven't read anything about changing the value of an array..

      I'm currently sitting in VS making some practice programs, just finished a 12 x 12 multiplication table to practice for loops! :)
      You may call me char 71 97 100 100 97 109.
    • Having the ability to control your own memory management is why I use C++, it has alot of power, but you have to be careful!
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz
    • Effective pointer usage is crucial to understanding and using C++. It's one of those subjects that all programmers get confused by the first time they hear it. "Oh, it's a memory address? Sure, I guess that's useful." Then it starts to really sync in and, eventually, pointers become the norm. I probably have more pointer variables in my code than non-pointer variables. Most books do a terrible job explaining what a pointer does or how it works.

      The concept is simple: A pointer is exactly like any other variable. Just like a float holds a real number or an int holds an integer, a pointer holds a memory address. That memory address can be anything, but since C++ is a strongly typed language, you typically define the type of thing it points to.

      Source Code

      1. int x = 5;
      2. int* pX = &x; // points to x
      3. printf("0x%x", pX); // this will print something like 0xd3dfae25


      You don't have to though:

      Source Code

      1. void* pGenericPtr = &x;


      The '&' operator retrieves the memory address of a variable. That's all it does.

      Source Code

      1. printf("0x%x", &x); // this will print 0xd3dfae25, since that's the address


      You have to use it when assigned to a pointer because, like everything else in C++, pointers are a type. You can't safely assign an int to a char, just like you can't safe assign an int to a pointer. Although you CAN cast an int into a pointer, just like can cast an int into a char. You can add and subtract values as well. Remember, pointers are really just normal variables.

      The one magic thing you can do with pointers that you can't do with other variables is dereferencing. Dereferencing a pointer makes it behave like a variable of the type the pointer is pointing to.

      Source Code

      1. printf("0x%x", *pX); // note the * syntax to dereference: this will print 0xa


      You can do this with object pointers as well, and even call functions:

      Source Code

      1. (*pSomeObject).DoStuff();


      That looks terrible, so there's cleaner syntax:

      Source Code

      1. pSomeObject->DoStuff();


      Pointers are great. They let you pass around very complex objects and do things like object comparisons incredibly cheaply. The size of a pointer is equal to the machine word (32-bits on a 32-bit machine, 64-bits on a 64-bit machine, etc.), so the system is optimized to handle them.

      As others have mentioned, they also give you access to dynamic memory, which is a powerful concept. In C++, you have direct and absolute control over every byte you allocate. This is critical for certain systems (the DS, for example, has 4 MB of RAM and if you run out, the device locks up). Memory allocation is also expensive, so you can do trick like allocate large blocks of memory up front and divvy them out during run-time. You can see an example of this in my Memory Pool implementation in GCC (I think I talk about it in Chapter 3). This isn't true (or it's less true) in other languages like Lua. In C++, you directly allocate and destroy everything. In a language like Lua, you allocate memory by creating an object. Once there are no more references to it, it gets marked for garbage collection and some other process comes to clean it up.

      Another use of pointers is that can be ambiguous. You can have a pointer to a base class and yet assign the address of a subclass to it. It'll work just fine. In fact, that's how polymorphism works.

      These are pretty advanced subjects, but the point is, pointers are critical to high-performance game development. It's worth really taking the time to understand how they work.

      -Rez
    • Thanks a lot for that Rez. I'm certainly not moving forward until I fully grasp how they operate. Thanks to everyone for their input, it's a community like this that I love being apart of!

      Now off to my practice program to see them in action more :)
      You may call me char 71 97 100 100 97 109.
    • Originally posted by Gaddam

      Source Code

      1. (*(*(coffee+ i)) + j)


      For what it's worth, you "shouldn't" see code like that. I put shouldn't in quotes because inevitably you will run into unclean, hard-to-read code. Generally speaking, you want to write code to be readable by other people, so you should avoid writing something like that. I don't see what that could be used for, but I would express it like this (assuming coffee is an array):

      Source Code

      1. int coffeeOffset = coffee[j];
      2. int value = coffee[coffeeOffset + j];


      Now if coffee isn't an array, then you shouldn't be doing pointer arithmetic on it. Just because something works, doesn't mean it's the right way to do things :)

      Cheers,
      James
    • I agree with that. For example, here's a function I just ran across a couple minutes ago in our code:

      Source Code

      1. template<class T>
      2. bool InitializeAction(PyObject* kwargs, void *action)
      3. {
      4. return InitializeActionImpl(kwargs, *(static_cast<T *>(action)));
      5. }


      *sigh*

      -Rez
    • I would say I have a concrete grasp of C++ memory handling, but I still find myself doing stupid things, like for some reason I thought I should do this

      Source Code

      1. *(int*)0


      Somehow my tired brain thought this was a good solution to have a pointer to a variable of value 0. Waking up the next morning, I didn't realize how I thought it would work or what I ven needed it for in the first place lol.
      PC - Custom Built
      CPU: 3rd Gen. Intel i7 3770 3.4Ghz
      GPU: ATI Radeon HD 7959 3GB
      RAM: 16GB

      Laptop - Alienware M17x
      CPU: 3rd Gen. Intel i7 - Ivy Bridge
      GPU: NVIDIA GeForce GTX 660M - 2GB GDDR5
      RAM: 8GB Dual Channel DDR3 @ 1600mhz
    • I did a bit of practice with them today, and went over functions again. I can see they are quite useful with functions and once I complete the classes section I'm sure I'll get that 'ah-ha' moment.

      I was working on an exercise that would take an const char array with 5 elements, and trying to see if they were Palindromes. I was able to get everything setup.

      I could find the length of an element in an array.
      I was able to copy the array to a new array. But I wanted to copy it reverse, that I couldn't figure out.
      I had a compare clause waiting to be tested, it was working great on the 2 array's because everything matched. So I was going to further alter it to check and change the value of a bool to give output to the user.

      Shew, it's been a busy few days but I feel like I'm finally making progress. :)

      The basic stuff was so easy compared to the more advanced features of the C++ language, I'm not afraid.. over time I'll conquer them all!
      You may call me char 71 97 100 100 97 109.
    • To do a forward copy, you're basically doing this:

      Source Code

      1. source = <start of source array>
      2. target = <start of target array>
      3. *target = *source
      4. <change source to point to next item>
      5. <change target to point to next item>


      To do a reverse copy, you just change your source parameter (or you could change your target parameter):

      Source Code

      1. source = <END of source array>
      2. target = <start of target array>
      3. *target = *source
      4. <change source to point to PREVIOUS item>
      5. <change target to point to next item>


      Hopefully that makes sense.

      As far as "comparing arrays" goes, there are two different things you might be checking. If you have "int* array1" and "int* array2", if you do "array1 == array2" you are seeing if they both point to the same array. If you loop through all of the items in the array:

      Source Code

      1. for(int i = 0; i < arrayLength; ++i)
      2. {
      3. check(array1[i] == array[2]);
      4. }


      Then you're actually checking if the arrays contain the same values. Those are important differences to note.

      Just so I can tailor future responses, having you worked in C# or Java before?

      James
    • By the way, the in-place copy that James just showed you is probably the most common interview question I've gotten.

      -Rez
    • Hey James,

      I've used PHP for awhile, but it was always modular with includes. I never got into the OOP side using classes, but it probably would have cut my code base in half to use! That was the start to my desire to program, but I've always wanted to do C++ programming. I set a goal and now I'm working to achieve it.



      Rez,

      That's good to know! :)


      I think when I get some free time later today, I will do my best to complete the program to check for palindromes. I will post it back here when I'm done.
      You may call me char 71 97 100 100 97 109.
    • James,

      I sat down and worked out copying a string here is my result:

      C Source Code

      1. // Include System Files
      2. #include <iostream>
      3. #include <iomanip>
      4. // Include Namespaces used
      5. using std::cout;
      6. using std:: cin;
      7. using std::endl;
      8. int main()
      9. {
      10. // Test array's
      11. char text[20] = "lid off a daffodil.";
      12. char textTwo[20] = " ";
      13. // Setup a for loop with 2 counters for both arrays
      14. for (int i = -1; j = 19; i < 19, j > -1;)
      15. {
      16. textTwo[j] = text[i];
      17. ++i; // increment i to point to next row from source
      18. --j; // deincrement j to point to next row in target
      19. }
      20. cout << "Original String: " << text << endl;
      21. cout << "Copied Result: " << textTwo << endl;
      22. return 0;
      23. }
      Display All


      This will output:

      Original String: lid off a daffodil.
      Copied String: .lidoffad a ffo dil


      So I was able to do it after all.
      You may call me char 71 97 100 100 97 109.
    • The idea looks correct. I only see a couple of issues. The first is that it won't compile. You need a comma between i = -1 and j = 19 rather than a semi-colon or C++ will think it's the second component of the for loop.

      Once that's fixed, it'll compile and print out your reversed string with a bunch of garbage at the end. Strings work in C by having a terminating 0 at the end. That's how functions like printf() or the cout object work without you having to pass in a size. Remember, a pointer just points to the first element of the string. The terminating 0 is what tells these functions when that string is done.

      The fix is easy. Just add this after your for loop:

      Source Code

      1. textTwo[19] = '\0';


      Once you do that, the program will work just fine.

      If you want to get REALLY fancy, see if you can figure out how to reverse the string without the need for the second string variable.

      -Rez
    • It was actually a typo when I was copying it to the forum, it was there! :) If I just copy and paste the code it loses the indentation.

      I assumed, which was wrong of me that the copy would include the terminating string. It's good to know that you also have to provide it! I didn't get any random garbage in my print out, possibly because I initialized the array with blank values?

      I will have to see if I can get fancy now, because that would be really cool! I'll post back with my solution.
      You may call me char 71 97 100 100 97 109.
    • Ok here goes!

      So first I figured you'd have to read the array from 0 to '\0' and then re-arrange the array from the end to the beginning. But without a 2nd array to spit the string into. That has me stumped.. thanks for that! :P

      I decided to use 2 while loops, 1 to go from start to end in order to keep track of my counter, then another while loop to re-arrange the array and send to the screen.

      So far:

      Source Code

      1. // includes left out
      2. char text[20] = "lid off a daffodil."; // Something to work with
      3. int i(0); // counter
      4. while(text[i] != '\0') { i++; } // While not at the end, increment i
      5. while(--i >= 0) // While decrementing to go backwards until 0
      6. {
      7. // Print the re-arranged array
      8. }
      9. ... // left out
      Display All


      I looked up the printf you mentioned but it wouldn't print the reverse, it was cool watching it assemble the sentence though! Getting sent to the output stream is what is stumping me.
      You may call me char 71 97 100 100 97 109.