Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Regarding the validity of &hellip;</p> <pre><code>alignas(int) char c[sizeof(int)]; int * i = reinterpret_cast&lt;int*&gt;(c); </code></pre> <p>The <code>reinterpret_cast</code> itself is OK or not, in the sense of producing a useful pointer value, depending on the compiler. And in this example the result isn't used, in particular, the character array isn't accessed. So there is not much more that can be said about the example as-is: it just <em>depends</em>.</p> <p>But let's consider an extended version that does touch on the aliasing rules:</p> <pre><code>void foo( char* ); alignas(int) char c[sizeof( int )]; foo( c ); int* p = reinterpret_cast&lt;int*&gt;( c ); cout &lt;&lt; *p &lt;&lt; endl; </code></pre> <p>And let's only consider the case where the compiler guarantees a useful pointer value, one that would place the pointee in the same bytes of memory (the reason that this depends on the compiler is that the standard, in §5.2.10/7, only guarantees it for pointer conversions where the <em>types</em> are alignment-compatible, and otherwise leave it as "unspecified" (but then, the whole of §5.2.10 is somewhat inconsistent with §9.2/18).</p> <p>Now, one interpretation of the standard's §3.10/10, the so called "strict aliasing" clause (but note that the standard does not ever use the term "strict aliasing"),</p> <blockquote> <p>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:</p> <ul> <li>the dynamic type of the object,</li> <li>a cv-qualified version of the dynamic type of the object,</li> <li>a type similar (as defined in 4.4) to the dynamic type of the object,</li> <li>a type that is the signed or unsigned type corresponding to the dynamic type of the object,</li> <li>a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,</li> <li>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),</li> <li>a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,</li> <li>a <code>char</code> or <code>unsigned</code> <code>char</code> type.</li> </ul> </blockquote> <p>is that, as it itself says, concerns the <em>dynamic type</em> of the object residing in the <code>c</code> bytes.</p> <p>With that interpretation, the read operation on <code>*p</code> is OK if <code>foo</code> has placed an <code>int</code> object there, and otherwise not. So in this case, a <code>char</code> array is accessed via an <code>int*</code> pointer. And nobody is in any doubt that <em>the other way</em> is valid: even though <code>foo</code> may have placed an <code>int</code> object in those bytes, you <em>can</em> freely access that object as a sequence of <code>char</code> values, by the last dash of §3.10/10.</p> <p>So with this (usual) interpretation, after <code>foo</code> has placed an <code>int</code> there, we can access it as <code>char</code> objects, so at least one <code>char</code> object exists within the memory region named <code>c</code>; and we can access it as <code>int</code>, so at least that one <code>int</code> exists there also; and so <a href="https://stackoverflow.com/a/12613099/464581">David&rsquo;s assertion in another answer</a> that <code>char</code> objects cannot be accessed as <code>int</code>, is incompatible with this usual interpretation.</p> <p>David's assertion is also incompatible with the most common use of placement new.</p> <p>Regarding what other possible interpretations there are, that perhaps could be compatible with David's assertion, well, I can't think of any that make sense.</p> <p>So in conclusion, as far as the Holy Standard is concerned, merely casting oneself a <code>T*</code> pointer to the array is practically useful or not depending on the compiler, and accessing the pointed to could-be-value is valid or not depending on what's present. In particular, think of a trap representation of <code>int</code>: you would not want that blowing up on you, if the bitpattern happened to be that. So to be safe you have to know what's in there, the bits, and as the call to <code>foo</code> above illustrates <em>the compiler can in general not know that</em>, like, the g++ compiler's strict alignment-based optimizer can in general not know that&hellip;</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. COYou have not understood what I said. My assertion is that a `char` **object** cannot be accessed through an `int` pointer. Your assertion is that once you replace the `char` object with an `int` object through placement new you can access the `int` object through an `int` pointer. You are **not** accessing a `char` through the `int` pointer, you are accessing an `int` that was created in the same memory location previously held by (multiple) `char` objects. Learn to read.
      singulars
    2. CO@David: when u say "learn to read", that is a good idea. it seems that you're suffering from some misconception that c++ is like python (say), a dynamically typed language. it's not: those bytes are not endowed with associated dynamic type information, and furthermore, accessing the char objects means that they're there (you can't very well access that which isn't there). in short your logic is completely lacking. *maybe* due to a fundamental misconception as i've now outlined, and i really hope that that's it.
      singulars
    3. COSo, is your claim that this is correct or incorrect (assume 32bit int): `float f; int* p = new (&f) int(1); cout << *p;`. And if it is incorrect, why? Note that I did not use *dynamic* in the sense of holding RTTI information, but as the actual type of the object in the memory location. Is there a `float` object *after* placement new? (If you think there is, read the object lifetime chapter in the standard) Is it legal to do `cout << f` after the placement new? What you fail to see is that you are saying the same thing I said, but failing to see they are the same thing.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload