2
int val{ 100 };
int* ptr1 = (int*)val;
int* ptr2 = ptr1 + 5;
std::cout << ptr2 << '\n' << (int)ptr2 << std::endl;

In this code example the result of (int*)val is 00000064, but I don't understand why. I also don't understand why (int)ptr2 is 120.

Zig Razor
  • 3,381
  • 2
  • 15
  • 35
  • 1
    `int* ptr2 = ptr1 + 5;` invokes *undefined behavior* – UnholySheep Nov 27 '20 at 10:43
  • 1
    What did you expect instead of `120` and why? – Mat Nov 27 '20 at 10:45
  • `64` in hexadecimal is `100`, which is exactly what you assign the pointer to. – Ted Klein Bergman Nov 27 '20 at 10:45
  • you can't cast an int to an int-pointer. dereferencing such a pointer causes undefined behaviour. use: int* ptr1 = &val; – Creepsy Nov 27 '20 at 10:46
  • `std::cout << ptr2 << '\n' << (int)ptr2 << std::endl;` ... sure you are printing (int*)val anywhere there? – String.Empty Nov 27 '20 at 10:46
  • @UnholySheep Why is that? That looks like defined behavior to me. It'll probably not point to anything useful so dereferencing it won't work, but I don't see how that's undefined behavior. – Ted Klein Bergman Nov 27 '20 at 10:47
  • 3
    @TedKleinBergman pointer arithmetic is only defined within the bounds of an array (including up to one past the end). So `ptr1 + 1` would be ok (since a single element is treated as a one element array), but `ptr1 + 2` is already UB – UnholySheep Nov 27 '20 at 10:49
  • @TedKleinBergmann Also surprised that this is UB, I expected it to be "mathematically fine, but just pointing to garbage". Thanks! :) Found this interesting: [pointer arightmatics and UB](https://stackoverflow.com/questions/56360316/c-standard-regarding-pointer-arithmetic-outside-arrays) – Cedric Nov 27 '20 at 10:58
  • @UnholySheep since `ptr1` doesn't point to any object, even `ptr1+1` is UB. – n. m. could be an AI Nov 27 '20 at 10:59
  • Are you asking why the difference between ptr1 and ptr2 is 20 istead of say 5? – n. m. could be an AI Nov 27 '20 at 11:02

2 Answers2

3

Analyzing line per line:

int* ptr1 = (int*)val;

Assign the decimal value 100 to the pointer ptr1;

int* ptr2 = ptr1 + 5;

This instuction invokes undefined behaviour, the algebric operation over pointer is allowed only in array context.

std::cout << ptr2 << '\n' << (int)ptr2 << std::endl;

This instruction can print everything due to the previous undefined behaviour.

The the result of (int*)val is 00000064 because is the representation of decimal value 100 in hexadecimal notation

Zig Razor
  • 3,381
  • 2
  • 15
  • 35
  • Suggested improvement: Add the information that `ptr2` ends up being 120 because that is `5 * sizeof( int )` (i.e. that pointer arithmetic increments in `sizeof( T )` steps). Plus (and that helped me a lot understanding pointers back then), add that *dereferencing* a pointer is only valid (i.e., not UB) *if it actually points to an object of the given type*. – DevSolar Nov 27 '20 at 11:03
1

Step by step:

int* ptr1 = (int*)val;

After executing this instruction ptr1 has decimal value 100 (00000064 in hexadecimal).

int* ptr2 = ptr1 + 5;

Now ptr2 has the same memory adress of ptr1, shifted by 5 units. It is shifted by 5 * (4 bytes) = 20 bytes. The memory address represented by ptr2 is (00000078) This is the reason why (int)ptr2 is 120 (100 + 20).

Can this reasoning make sense?

Losak
  • 26
  • 4