Pointer notation is confusing.

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

    • That'll certainly print the string in reverse, but what I meant was actually reversing the string itself. Fill in this function:

      Source Code

      1. void ReverseString(char* str, size_t strSize)
      2. {
      3. //
      4. }


      str is a null-terminated string and strSize is the size of that string. When called, I would expect str to be reversed. For example:

      Source Code

      1. char* testString = "bunny";
      2. ReverseString(testString, strlen(testString)+1);
      3. cout << testString; // this will print "ynnub"


      It's a little tricky, but you can reverse the string without the need for a second string.

      -Rez
    • To make things even more confusing, I have a question as well. :)

      Source Code

      1. struct S{
      2. double x;
      3. double y;
      4. double z;
      5. S() : x(3.1) , y(1.2), z(3.4) {}
      6. };
      7. int main()
      8. {
      9. S s1;
      10. int x = 3;
      11. int y = 4;
      12. int z = 6;
      13. std::cout << "In Struct, pointer arithmetic works correct." << std::endl
      14. << "Struct x: " << *(&(s1.x)+0) << std::endl // Prints 3.1
      15. << "Struct y: " << *(&(s1.x)+1) << std::endl// Prints 1.2 ok cool
      16. << "Struct z: " << *(&(s1.x)+2) << std::endl;// Prints 3.4 very cool
      17. std::cout << "These local variables in the main fail at pointer arithmetic. " << std::endl
      18. << "X: " << *(&x) << std::endl // Prints 3
      19. << "Y: " << *(&x-1) << std::endl // Prints 6, this is Z not Y!
      20. << "Z: " << *(&x-2) << std::endl;// Prints 3864604 what happened?
      21. std::cout << "Interesting fact that addresses are seem to be correct." << std::endl
      22. << "Address of X: " << (&x) << std::endl
      23. << "Address of Y: " << (&x-1) << std::endl
      24. << "Address of Z: " << (&x-2) << std::endl;
      25. return 0;
      26. }
      Display All


      What is the interesting stuff here is that, this works at my mac as intended. However local variables shown at the comments gives very wierd results for my Win7 pc. I think its about compilers but am i doing anything wrong here?
    • The C++ standard doesn't make any guarantees about how member variables are ordered within structs or classes so you can't assume any particular order. That's why you're getting different results on two different compilers.

      -Rez
    • Originally posted by kaykry
      I would have expected z to have the lowest address in memory since the stack grows upward to lower memory addresses. I was under the impression that local variables were pushed onto the stack in the order that they appear. Is that not correct?

      I actually remember reading an example where a buffer overflow spilled into the previously declared local variable and corrupted it's value.

      This is another place where the C++ standard doesn't really specify. Local variables are stored however the compiler decides to store them. Sometimes they're not stored in memory at all and the compiler keeps them entirely in CPU registers (though as soon as you ask for the address of a variable, it has to store it in memory).

      You really shouldn't write programs that are dependent on the order variables appear on the stack. If you need to kind of control, you should write an assembly language procedure and call it from C++ with __stdcall or another calling convention where the called function deals with stack clean up. (Also, you should question why you need such control.)

      -Rez
    • Originally posted by kaykry
      I don't need to write a program that needs that level of control. It's not something that I would ever depend on. I just like to stick my nose in there and find out what's going on. ;)

      Hahaha! That sounds exactly like me. ;)

      -Rez
    • Source Code

      1. void ReverseString(char* str, size_t strSize)
      2. {
      3. for(int i = 0; i < strSize / 2; i++)
      4. {
      5. char c = str[i];
      6. int e = strSize-1-i;
      7. str[i] = str[e];
      8. str[e] = c;
      9. }
      10. }


      Thats about as efficient as I could think of
      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
    • Yep, that's about right. :) You could make it more efficient, but that's not really something to worry about right now. The thing I was looking for was having two indexes and walking them towards each other, swapping the whole way. It's actually faster than the previous method of printing each character out. This algorithm is O(n/2) as opposed to O(n). In other words, you're only iterating over half the data. Also, printing anything to the console is SLOW, so doing it N times is VERY SLOW.

      Nice job. :)

      -Rez
    • Originally posted by rezination

      You really shouldn't write programs that are dependent on the order variables appear on the stack. If you need to kind of control, you should write an assembly language procedure and call it from C++ with __stdcall or another calling convention where the called function deals with stack clean up. (Also, you should question why you need such control.)

      -Rez


      My vector class depends on member variable construction order like this:

      Source Code

      1. struct Vector4D{
      2. //Constructors and other stuff..
      3. double x;
      4. double y;
      5. double z;
      6. double w;
      7. //Operator Overloading []
      8. double& operator[](int i) { return *(&x+i); }
      9. const double& operator[](int i) const { return *(&x+i); }
      10. };
      Display All


      I always found this solution pretty but I guess i have to remove it now:). By the way I looked at the "C++ Programming Book" by Bjarne Stroustrup, he mentions that order of the construction of class member objects are same as their declaration order when constructing the class. So, is this mean that built-in types are unordered at construction not the class objects?

      Edit: Maybe i am confusing construction order with order of objects in memory?

      The post was edited 3 times, last by column_vector ().

    • my eyes!!! my eyes!!! X(

      char c = str; // c will now be the start of str
      int e = strSize-1-i; // e will now be the end of str, decremented each loop
      str[i] = str[e]; // place the Ith element in the Eth element
      str[e] = c; // place last element at start of c

      EDIT: seeing if I can follow :)

      I didn't know you could put n/2 in condition of the for loop, interesting!!
      You may call me char 71 97 100 100 97 109.

      The post was edited 1 time, last by Gaddam ().

    • Sorry man, but it's not pretty at all, it's extremely hard to read. This is what we call "clever" code. It's code that is trying to do something clever without actually adding any value.

      One of the most important things you can do with code is communicate intent. If I saw that in the code base, I would be confused as to what you were doing and why. This is MUCH more elegant and easier to read:

      Source Code

      1. class Vector4
      2. {
      3. double x, y, z, w;
      4. public:
      5. // constructors, etc
      6. double GetX(void) const { return x; }
      7. double GetY(void) const { return y; }
      8. double GetZ(void) const { return z; }
      9. double GetW(void) const { return w; }
      10. };


      In the code above, it's much more clear exactly what the intent is and what's being returned. If I saw this:

      Source Code

      1. Vector4 vec(10, 20, 30, 40);
      2. return vec[1];


      I would have no idea what it was actually returning without looking at the code. But this:

      Source Code

      1. Vector4 vec(10, 20, 30, 40);
      2. return vec.GetY();

      That's very explicit. I know exactly what it's doing.

      C++ will construct variables in the order specified, but it still doesn't place any guarantees as to where those variables are actually stored. If you do need to guarantee that memory is contiguous, you have to use an array. That's really the only way to guarantee the order that things appear in memory, which would solve your problem.

      -Rez
    • Originally posted by Gaddam
      my eyes!!! my eyes!!! X(

      char c = str; // c will now be the start of str
      int e = strSize-1-i; // e will now be the end of str, decremented each loop
      str[i] = str[e]; // place the Ith element in the Eth element
      str[e] = c; // place last element at start of c

      EDIT: seeing if I can follow :)

      I didn't know you could put n/2 in condition of the for loop, interesting!!


      Sort of, first we store the first element of the string in c which is necessary to swap 2 elements, then we store the reverse index in e, which is faster then doing the strSize-1-i twice, we then do the swap, str[i] = str[e] stores the last element in the first, and str[e] = c stores the first element (which we saved) in the last.

      For loops can actually be anything, but to be useful they usually look the same, here are some variations

      Iterating with an integer

      Source Code

      1. for(int i = 0; i < SIZE; i++)
      2. {
      3. //Do Something with i
      4. }


      Iterating with an STL container

      Source Code

      1. for(auto it = gObjectList.begin(); it != gObjectList.end(); it++)
      2. {
      3. (*it)->DoSomething();
      4. }


      iterating using a tiny XML element pointer

      Source Code

      1. for(auto it = pNode; pNode; pNode = pNode->NextSiblingElement())
      2. {
      3. double x = 0.0;
      4. pNode->Attribute("x", &x);
      5. }


      They all look different but in essence they are accomplishing similar duties, a for loop has 3 sections each seperated by a ';', I always called them, the initialization, the condition, and the iteration.

      Source Code

      1. for(initialize; conditon; iterate)
      2. {
      3. }


      A for loop can actually be reproduced using other conditional operators

      Source Code

      1. int i = 0;
      2. while(i < SIZE)
      3. {
      4. //Do Something
      5. i++;
      6. }


      You can actually omit parts of the initializer as well for certain circumstances ie.

      Source Code

      1. int i = 0;
      2. for(; i < SIZE; i++)
      3. {
      4. //Do Something
      5. }
      6. cout << i << endl;


      In this case we needed i to be accessible after the loop

      Source Code

      1. for(auto it = gObjList.begin(); it != gObjList.end();)
      2. {
      3. auto it2 = it++;
      4. delete (*it2);
      5. gObjList.erase(it2);
      6. }


      In this rather useless case but example, we need to store the iterator, then increment it, then delete the stored iterator, if you deleted it before you iterated it you would get an error, and if you iterated it before you stored it you would have the wrong one.
      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
    • There are two different types of increment operator:

      Source Code

      1. i++; // post-increment
      2. ++i; // pre-increment


      The difference is simple: the variable is evaluated before the increment is applied in the case of a post-increment operator and after the increment is applied in a pre-increment operator. For example:

      Source Code

      1. int i = 5;
      2. if (i++ == 5)
      3. {
      4. // This will execute, because it's evaluated before i is incremented.
      5. // i will be 6 here.
      6. }
      7. // reset i
      8. i = 5;
      9. if (++i == 5)
      10. {
      11. // This won't be executed, because i is 6. It was incremented before
      12. // we evaluated it.
      13. }
      Display All


      Here's the catch: the post-increment operator will create a temp variable. This isn't a big deal in the case of integers, but it can kill your performance when using STL iterators on large data sets.

      In fact, you should never ever use the post-increment operator. Ever. There is never a time when the post-increment operator is better. Always use the pre-increment operator.

      The only exception is when you want to evaluate and increment in the same statement, which you should probably never do. You should break them up into multiple statements, especially because the assembly code will be exactly the same.

      Always be more explicit.

      -Rez
    • man I alway's use post increment, thanks for the tip.
      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
    • Originally posted by mholley519
      man I alway's use post increment, thanks for the tip.


      Back when I was first learning C (which, depressingly, is before some of you were born), I was taught to use post-increment. All sample code I saw used post-increment. It's a bad habit in programming books everywhere. :(

      It's also why I use pre-increment everywhere in the GCC code. I think Mike does do.

      -Rez
    • LOL Rez your just as old as me, and now you're making me feel old! :)

      Thanks for that clarification I appreciate it mholley!

      EDIT: I plugged it into VS2010, it compiles fine but complained about mismatch so I changed from int to size_t in the for loop, but still just crashes. For some reason int e =... causes a write exception.
      You may call me char 71 97 100 100 97 109.

      The post was edited 1 time, last by Gaddam ().

    • That is strange, I use VS2012 which shouldn't be any different, I don't usually use size_t but I know it is a type of varying size, try returning the code to the way it was but ignore the warning, it should work.

      Here is an article on size_t

      stackoverflow.com/questions/131803/unsigned-int-vs-size-t

      Really the code would work with all int's rather than size_t, size_t is used to accommodate very large file sizes;
      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

      The post was edited 1 time, last by mholley519 ().

    • I just wanted to thank you all again for your input, it was a bumpy road to start on but I am getting a lot more confident with using pointers.

      Now I'm moving into the class portion of my book, I completed functions and structures. I'm going to keep going slow and steady until I can completely understand.
      You may call me char 71 97 100 100 97 109.