简体   繁体   中英

Need help understanding pointer arithmetic

I'm having troubles understanding pointer arithmetic or how memory is assigned. In the code snippet below, I am trying to access the value of 'size = 1' which is located 8 bytes before 'test', but I don't get size's value and the value is not random. So I may have an issue with understanding bytes sizes. If void*, long, and char are 8 bytes should it matter when using pointer arithmetic?

#include <iostream>
using namespace std;

char arrayOfCrap[100];

void * what(){
    long * size ; 
    size = (long*)&arrayOfCrap[28];
    *size = 1;
    return ((void*) &arrayOfCrap[29]);
}

int main(){

    long * test;
    test =  (long*)what();
    *test = 1221;
    cout << "Value of test: " << *test << endl;
    cout << "Long number before test: " << *(test-1) << endl;
}

The code works when main moves forward from what()'s void* 'pointer:

#include <iostream>
using namespace std;

char arrayOfCrap[100];

void * what(){
    long * size ; 
    size = (long*)&arrayOfCrap[28];
    *size = 1;
    return ((void*) &arrayOfCrap[28]);  //change from above
}

int main(){

    long * test;
    test =  (long*)what();
    test++;                             //change from above
    *test = 1221;
    cout << "Value of test: " << *test << endl;
    cout << "Long number before test: " << *(test-1) << endl;
}

Your code is not locating *size eight bytes before *test :

size = (long*)&arrayOfCrap[28];

arrayOfCrap is char arrayOfCrap[100] so arrayOfCrap[28] is the char at offset 28 and arrayOfCrap[29] is the char at offset 29.

The reason test++ works is that test is of type long* , so incrementing it actually moves to the next position for a long, whereas incrementing a char* or using an index on a char array gives you the next position for a char .

You could also do one of these:

void * what(){
    long * size ; 
    size = (long*)&arrayOfCrap[28];
    *size = 1;
    return size+1;
}

void * what(){
    long * size ; 
    size = (long*)&arrayOfCrap[28];
    *size = 1;
    return ((void*) &arrayOfCrap[28 + sizeof(long)];
}

By the way, its not necessarily safe to take a pointer to just any memory location and treat it as a pointer to another type. Some platforms require some types to be 'aligned', or to have those types exist only at addresses that are multiples of a certain value. On those platforms reading or writing to an unaligned object may crash (bus error) or otherwise have undefined behavior. Also, some platforms may not crash or behave incorrectly, but have much better performance when reading/writing aligned objects. I know this is completely beside the point of your experimentation, but it's something you should know for real code. Here's an example of what not to do in real code:

int read_int(char *&c) {
  int out = *(int*)c; // c may not be properly aligned!
  c += sizeof(int);

  return out;
}

Unfortunately on a common platform, x86, unaligned access is usually just slow rather than something that will always cause a crash, so users of that platform have to be especially careful.

When you increment a pointer, it increments not by the pointer size, but by the size of the type of the pointer. A char* pointer increments by sizeof(char) , a long* pointer increments by sizeof(long)

sizeof(char *) , sizeof(long *) should be both the same size (generally 4 bytes on 32-bit systems, 8 bytes on 64-bit systems).

However, sizeof(char) and sizeof(long) are not the same.

You are confusing your pointer size with the integer size.

#include <iostream>
using namespace std;

int main()
{
    cout << "\n sizeof(char*)   " << sizeof(char *);
    cout << "\n sizeof(char)    " << sizeof(char);
    cout << "\n sizeof(long*)   " << sizeof(long *);
    cout << "\n sizeof(long)    " << sizeof(long);
}

See it in action here: http://ideone.com/gBcjS

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM