0

The following I have come across in the section 3.7.4.3/3:

An integer value is an integer representation of a safely-derived pointer only if its type is at least as large as std::intptr_tand it is one of the following:

[...]

— the result of an additive or bitwise operation, one of whose operands is an integer representation of a safely-derived pointer value P, if that result converted by reinterpret_cast<void*> would compare equal to a safely-derived pointer computable from reinterpret_cast<void*>(P).

Ok, let int *P = new int(1); be a some pointer and long p_int = <reinterpret_cast<long>(P); his integer representation. Consider the following code:

int *P = new int(1); //Safely-derived pointer
long p_int = <reinterpret_cast<long>(P); //Integer representation of safely derived pointer
long new_p_int = p_int + 10; // Result of an additive operation
void *new_P = reinterpret_cast<void*>(new_p_int);
void *P_cpnverting_to_void = reinterpret_cast<void*>(P);
cout << "P converted to void* = " << P_cpnverting_to_void << endl;
cout << "P after result of an additive operation = " << new_P << endl;

demo

The rule is not clear. How can the result pointer be compare equal reinterpret_cast(P)? They never be compare equal after applying additive operation. Could you possibly provide actual example reflecting the rule?

St.Antario
  • 26,175
  • 41
  • 130
  • 318

1 Answers1

2

The key point is the pointer resulting from reinterpret_cast<void*> must compare equal to a safely-derived pointer computable from reinterpret_cast<void*>(P).

It does not have to equal reinterpret_cast<void*>(P).

Consider the following example, where we exhibit equality with a safely derived pointer which computed from reinterpret_cast<void*>(P).

#include <iostream>
#include <stdint.h>

using namespace std;

int main(){
    int *P = new int(1); //Safely-derived pointer
    uint64_t p_int = reinterpret_cast<uint64_t>(P); 
    uint64_t new_p_int = p_int + 10; // Result of an additive operation
    void *new_P = reinterpret_cast<void*>(new_p_int);
    void *P_computed_from_void_star = reinterpret_cast<void*>(P) + 10;
    cout << "P converted to void* = " << P_computed_from_void_star << endl;
    cout << "P after result of an additive operation = " << new_P << endl;
}
merlin2011
  • 71,677
  • 44
  • 195
  • 329
  • -1. The code you provide even does not compile. Demo: http://coliru.stacked-crooked.com/a/7d484ca7aefa1f5b – St.Antario Aug 08 '14 at 04:07
  • @St.Antario, That's because your online compiler is interpreting warnings as errors. – merlin2011 Aug 08 '14 at 04:10
  • @St.Antario, There is naturally a warning when trying to arithmetic on a `void*`, but I am showing it merely to illustrate the rule that you asked about it. – merlin2011 Aug 08 '14 at 04:11
  • Coliru uses gcc 4.9.0 – St.Antario Aug 08 '14 at 04:11
  • @St.Antario, This code compiles on `gcc 4.8.1` with a warning. – merlin2011 Aug 08 '14 at 04:12
  • It is a bit unclear what expression `reinterpret_cast(P) + 10` reutrns in? I thought when we're using additive operator such that one operand is pointer to `T` we have to know `sizeof(T)` – St.Antario Aug 08 '14 at 04:13
  • @St.Antario, On my system, it does the arithmetic as if `void*` pointed to a one-byte quantity. – merlin2011 Aug 08 '14 at 04:14
  • Hmmm... Is there something restriction about pointer to void arithmetic into the Standard? – St.Antario Aug 08 '14 at 04:15
  • @St.Antario, That I am not sure about. However, the discussion under [this answer](http://stackoverflow.com/a/1666232/391161) might be relevant. – merlin2011 Aug 08 '14 at 04:16
  • @St.Antario, Well, I'm glad it compiles correctly on at least *one* online compiler. I normally only test on local `gcc` for code whose only purpose is to show a point. – merlin2011 Aug 08 '14 at 04:26
  • But from the topic that you cites I assume that such behavior is not standartized. That is, compiler must throw error normally. – St.Antario Aug 08 '14 at 04:30
  • Yes. So it is quite possible that computable from need not be possible in code. – merlin2011 Aug 08 '14 at 04:32