Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Pointer Maths

Pointer Maths

Scheduled Pinned Locked Moved C / C++ / MFC
questionperformance
9 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    KeithF
    wrote on last edited by
    #1

    Folks, Quick question in relation to the Pointer Maths in this program below, The Output is as follows: 1, 2, 3 . . . . . . . . . 245026, 245027, 245028 246017, 246018, 246019 247010, 247011, 247012 248005, 248006, 248007 249002, 249003, 249004 The Last Record is : 245028 Using the MoveBack function I expected the output to be 248007, the record before the current record, however it seems we move back 12 blocks of memory to 245028 and not the 12bytes I expected. Can someone explain to me whats going on here and how I can modify the code to get 248007 from the function? Thanks In Advance

    #include "stdafx.h"
    #include <conio.h>

    typedef struct MyStruct{
    int i;
    int j;
    int k;
    } TheStruct;

    int MoveBack(int *iPos);

    int main(int argc, char* argv[])
    {
    TheStruct ts[500];
    int i = 0;

    for(i = 0; i < 500; i++)
    {
    	ts\[i\].i = i \* i + 1;
    	ts\[i\].j = i \* i + 2;
    	ts\[i\].k = i \* i + 3;
    }
    
    for(i = 0; i < 500; i++)
    {
    	printf("%ld, %ld, %ld \\r\\n" ,ts\[i\].i ,ts\[i\].j, ts\[i\].k);
    
    	if(i == 499)
    	{
    		//Pointer - Move back to last record
    		printf("The Last Record is : %ld" , MoveBack(&ts\[i\].k));
    	}
    	
    }
    
    while(!getch());
    
    return 0;
    

    }

    int MoveBack(int *iPos)
    {
    int *i = iPos - sizeof(TheStruct);
    return *i;
    }

    S L 2 Replies Last reply
    0
    • K KeithF

      Folks, Quick question in relation to the Pointer Maths in this program below, The Output is as follows: 1, 2, 3 . . . . . . . . . 245026, 245027, 245028 246017, 246018, 246019 247010, 247011, 247012 248005, 248006, 248007 249002, 249003, 249004 The Last Record is : 245028 Using the MoveBack function I expected the output to be 248007, the record before the current record, however it seems we move back 12 blocks of memory to 245028 and not the 12bytes I expected. Can someone explain to me whats going on here and how I can modify the code to get 248007 from the function? Thanks In Advance

      #include "stdafx.h"
      #include <conio.h>

      typedef struct MyStruct{
      int i;
      int j;
      int k;
      } TheStruct;

      int MoveBack(int *iPos);

      int main(int argc, char* argv[])
      {
      TheStruct ts[500];
      int i = 0;

      for(i = 0; i < 500; i++)
      {
      	ts\[i\].i = i \* i + 1;
      	ts\[i\].j = i \* i + 2;
      	ts\[i\].k = i \* i + 3;
      }
      
      for(i = 0; i < 500; i++)
      {
      	printf("%ld, %ld, %ld \\r\\n" ,ts\[i\].i ,ts\[i\].j, ts\[i\].k);
      
      	if(i == 499)
      	{
      		//Pointer - Move back to last record
      		printf("The Last Record is : %ld" , MoveBack(&ts\[i\].k));
      	}
      	
      }
      
      while(!getch());
      
      return 0;
      

      }

      int MoveBack(int *iPos)
      {
      int *i = iPos - sizeof(TheStruct);
      return *i;
      }

      S Offline
      S Offline
      Stefan_Lang
      wrote on last edited by
      #2

      Adding or subtracting from a pointer will always be done in multiples of the size of the type pointed to. In this case, MoveBack subtracts 12 times the size of an int from the address, since i points to an int (or at least that's how you declared it). If you don't want that, you have to use void* rather than int*. That said, it's a horrible idea to cast a pointer into an array of some struct to int*! Why don't you just pass a pointer to MyStruct instead? Also, it's an even worse idea to dereference an int pointer that in truth points to a struct. This may or may not work, depending on the compiler. And if you ever choose to modify your struct later, the code will likely break (provided it did actually work before).

      MyStruct* MoveBack(const MyStruct* p)
      {
      return p-1; // moves pointer to previous struct in array
      }

      // to use it do this:
      printf("The Last Record is : %ld" , MoveBack(&ts[i])->k);

      P.S.: Note that this solution a) makes the function independent of the definition of MyStruct b) gets rid of error prone type casts c) removes the need to use sizeof d) is actually shorter, to the point that you could inline it, or simply forgo the function alltogether (e. g., above you could write (&ts[i]-1)->k) P.P.S.: you could of course just use ts[i-1].k That would be technically equivalent to the code I suggested under d) above

      modified on Tuesday, July 12, 2011 9:59 AM

      L 1 Reply Last reply
      0
      • K KeithF

        Folks, Quick question in relation to the Pointer Maths in this program below, The Output is as follows: 1, 2, 3 . . . . . . . . . 245026, 245027, 245028 246017, 246018, 246019 247010, 247011, 247012 248005, 248006, 248007 249002, 249003, 249004 The Last Record is : 245028 Using the MoveBack function I expected the output to be 248007, the record before the current record, however it seems we move back 12 blocks of memory to 245028 and not the 12bytes I expected. Can someone explain to me whats going on here and how I can modify the code to get 248007 from the function? Thanks In Advance

        #include "stdafx.h"
        #include <conio.h>

        typedef struct MyStruct{
        int i;
        int j;
        int k;
        } TheStruct;

        int MoveBack(int *iPos);

        int main(int argc, char* argv[])
        {
        TheStruct ts[500];
        int i = 0;

        for(i = 0; i < 500; i++)
        {
        	ts\[i\].i = i \* i + 1;
        	ts\[i\].j = i \* i + 2;
        	ts\[i\].k = i \* i + 3;
        }
        
        for(i = 0; i < 500; i++)
        {
        	printf("%ld, %ld, %ld \\r\\n" ,ts\[i\].i ,ts\[i\].j, ts\[i\].k);
        
        	if(i == 499)
        	{
        		//Pointer - Move back to last record
        		printf("The Last Record is : %ld" , MoveBack(&ts\[i\].k));
        	}
        	
        }
        
        while(!getch());
        
        return 0;
        

        }

        int MoveBack(int *iPos)
        {
        int *i = iPos - sizeof(TheStruct);
        return *i;
        }

        L Offline
        L Offline
        Legor
        wrote on last edited by
        #3

        When using sizeof with a structure it is not guaranteed that you get the sum of the single components due to Structure padding (wiki for it). Just printf the sizeof() of your struct and you will see that its not 12 Bytes. Anyway it is very unclear to me why are you even trying to do it this way. Dont mess with addresses and pointers in such an unsafe way. Who even tells you that you could just decrease the given int pointer and it would still point to a valid adress. E.g. just use the indices of the array to get the last element.

        R E L 3 Replies Last reply
        0
        • S Stefan_Lang

          Adding or subtracting from a pointer will always be done in multiples of the size of the type pointed to. In this case, MoveBack subtracts 12 times the size of an int from the address, since i points to an int (or at least that's how you declared it). If you don't want that, you have to use void* rather than int*. That said, it's a horrible idea to cast a pointer into an array of some struct to int*! Why don't you just pass a pointer to MyStruct instead? Also, it's an even worse idea to dereference an int pointer that in truth points to a struct. This may or may not work, depending on the compiler. And if you ever choose to modify your struct later, the code will likely break (provided it did actually work before).

          MyStruct* MoveBack(const MyStruct* p)
          {
          return p-1; // moves pointer to previous struct in array
          }

          // to use it do this:
          printf("The Last Record is : %ld" , MoveBack(&ts[i])->k);

          P.S.: Note that this solution a) makes the function independent of the definition of MyStruct b) gets rid of error prone type casts c) removes the need to use sizeof d) is actually shorter, to the point that you could inline it, or simply forgo the function alltogether (e. g., above you could write (&ts[i]-1)->k) P.P.S.: you could of course just use ts[i-1].k That would be technically equivalent to the code I suggested under d) above

          modified on Tuesday, July 12, 2011 9:59 AM

          L Offline
          L Offline
          Legor
          wrote on last edited by
          #4

          What if p points to element 0 of the array? How would you check for this?

          S 1 Reply Last reply
          0
          • L Legor

            What if p points to element 0 of the array? How would you check for this?

            S Offline
            S Offline
            Stefan_Lang
            wrote on last edited by
            #5

            You can't. Not inside MoveBack() anyway. Which is yet another good argument not to meddle with pointers recklessly. The only way to ensure a pointer is inside the scope of an array is to compare it to the start address, and only the function that defined the array knows it. So if you really wanted a 'safe' MoveBack function, you'd have to add a parameter, like this:

            MyStruct* MoveBack_s(const MyStruct* p, const MyStruct* parray)
            {
            MyStruct* result = 0;
            if (p > parray)
            result = p-1;
            return result;
            }

            Of course, even this function is not safe if you pass it a pointer to the start of a different array... The only way to be truly safe is not to use pointers, but iterators, such as those used for the STL class vector. They contain references to the container they refer to and therefore can check their boundaries themselves.

            1 Reply Last reply
            0
            • L Legor

              When using sizeof with a structure it is not guaranteed that you get the sum of the single components due to Structure padding (wiki for it). Just printf the sizeof() of your struct and you will see that its not 12 Bytes. Anyway it is very unclear to me why are you even trying to do it this way. Dont mess with addresses and pointers in such an unsafe way. Who even tells you that you could just decrease the given int pointer and it would still point to a valid adress. E.g. just use the indices of the array to get the last element.

              R Offline
              R Offline
              Rick York
              wrote on last edited by
              #6

              I made a code snippet to print the size of his structure and it was in fact 12 bytes.

              L 1 Reply Last reply
              0
              • L Legor

                When using sizeof with a structure it is not guaranteed that you get the sum of the single components due to Structure padding (wiki for it). Just printf the sizeof() of your struct and you will see that its not 12 Bytes. Anyway it is very unclear to me why are you even trying to do it this way. Dont mess with addresses and pointers in such an unsafe way. Who even tells you that you could just decrease the given int pointer and it would still point to a valid adress. E.g. just use the indices of the array to get the last element.

                E Offline
                E Offline
                enhzflep
                wrote on last edited by
                #7

                Why on earth was this rated as a bad answer? Each of the points made are valid and important. Let's see if a 5 won't help!

                1 Reply Last reply
                0
                • L Legor

                  When using sizeof with a structure it is not guaranteed that you get the sum of the single components due to Structure padding (wiki for it). Just printf the sizeof() of your struct and you will see that its not 12 Bytes. Anyway it is very unclear to me why are you even trying to do it this way. Dont mess with addresses and pointers in such an unsafe way. Who even tells you that you could just decrease the given int pointer and it would still point to a valid adress. E.g. just use the indices of the array to get the last element.

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  Legor wrote:

                  When using sizeof with a structure it is not guaranteed that you get the sum of the single components due to Structure padding

                  But it doesn't matter since you will always get the size of the actual structure as created by the compiler, so you can still use sizeof to increment a void pointer. However, as you rightly point out, that is a stupid way to do it since normal increment/decrement or indexing is the correct way.

                  The best things in life are not things.

                  1 Reply Last reply
                  0
                  • R Rick York

                    I made a code snippet to print the size of his structure and it was in fact 12 bytes.

                    L Offline
                    L Offline
                    Legor
                    wrote on last edited by
                    #9

                    Well i was a bit fast with saying that it will not be 12 bytes. Of course it depends on the compiler. I just wanted to state that its not allways 12 bytes.

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups