2

We know in general sizeof(long) != sizeof(int). But which parts of the (C++11) standard disallow aliasing long* through int*? Is it just by omission in [conv.ptr], the aliasing rules in [basic.lval], or something else?

void f()
{
    static_assert(sizeof(int) == sizeof(long), "");
    long x[] = {1, 2};
    int* y = x; // error: invalid conversion from ‘long int*’ to ‘int*’ [-fpermissive]
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118

2 Answers2

0

Yes it is by omission in [conv.ptr] and the applicable paragraph is in [expr.reinterpret.cast],

7 An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type "pointer to T1" is converted to the type "pointer to cv T2", the result is static_cast<cv T2*>(static_cast<cv void*>(v)) if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type "pointer to T1" to the type "pointer to T2" (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.

You have to use reinterpret_cast<int*>(...).


EDIT. There is a concern in the comments that I am making more visible in this edit, that this is not a language-lawyer question but that the intention is to use the pointer. I am not sure how the concern came about, as it is rather obvious that one can simply C-cast without asking, but if there is doubt - the pointer cast to int* violates strict aliasing rules.

That is, an undefined behaviour may arise from the fact that you break the compiler's assumption that pointers of different types could never point to the same memory location.

Community
  • 1
  • 1
mockinterface
  • 14,452
  • 5
  • 28
  • 49
0

long and int are two distinct types, even if they are the same size, so I think the invalid conversion is due to [basic.lval.10]

If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:

  • the dynamic type of the object,
  • a cv-qualified version of the dynamic type of the object,
  • a type similar (as defined in 4.4) to the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to the dynamic type of the object,
  • a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
  • an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
  • a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
  • a char or unsigned char type.

As a side note, if [basic.lval] did not exist, there would be other issues: same size doesn't mean same representation / range.

There's no guarantee that the value bits in int correspond precisely to the value bits in a long.

manlio
  • 18,345
  • 14
  • 76
  • 126