union String
{
char as_array[sizeof(int)];
int as_int;
};
Am 14.07.2015 11:42 schrieb "Fabio Fracassi" <f.fra...@gmx.net>:
>
>
>
> On 14.07.2015 11:19, Andrzej Krzemieński wrote:
>>
>> Hi,
>> I am unable to figure out from the Standard what it has to say about type-punning with unions.
>>
>> I have the following union:
>> union String
>> {
>> char as_array[sizeof(int)];
>> int as_int;
>> };
>>
>> I intend to initialize member as_array, but later access member as_int. The goal is to perform a sort of reinterpret cast by accessing memory through a different member. The question is: what does the Standard has to say about it?
>
>
>> Is this an undefined behavior? But if so, can you point me to the relevant sections?
>>
>> Or is this part of the standard underspecified? In that case, does someone know what the intention is?
>>
>
> If I remember the last discussion (on the undefined behavior list) about this correctly, it is intentionally undefined behavior.
> I also interpret §[class.union]/1 as forbidding it, also it is not very explicit about it. The first sentence reads:
> "In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time."
> Which I interpret as forbidding accessing a unions member that is not the currently active one.
If so, this would not need to be banned in constexpressions directly, but merely by its undefined behavior (and reading an initial common sequence is intended to be allowed there aswell).
Richard?
On 2015–07–14, at 5:42 PM, Fabio Fracassi <f.fra...@gmx.net> wrote:IIRC the only way to do legal type pruning is using memcpy.
For this to work, aliasing rules need to be transitive or am I missing something?
On 2015–07–14, at 5:50 PM, 'Johannes Schaub' via ISO C++ Standard - Discussion <std-dis...@isocpp.org> wrote:> You can pun to character types with reinterpret_cast. Other types require something like memcpy, which works because it treats each of the two objects as a character sequence. Anything that behaves that way is sufficient, though, including std::copy<char const*, char*>.
>For this to work, aliasing rules need to be transitive or am I missing something?
Am 14.07.2015 11:57 schrieb "David Krauss" <pot...@gmail.com>:
>
>
>> On 2015–07–14, at 5:50 PM, 'Johannes Schaub' via ISO C++ Standard - Discussion <std-dis...@isocpp.org> wrote:
>>
>> > You can pun to character types with reinterpret_cast. Other types require something like memcpy, which works because it treats each of the two objects as a character sequence. Anything that behaves that way is sufficient, though, including std::copy<char const*, char*>.
>> >
>>
>> For this to work, aliasing rules need to be transitive or am I missing something?
>
>
> Nothing is transitive. The bytes of object A are copied into storage buffer B. Now B can be treated as another object of some other POD type, provided that the object representation is valid. Upon the first access, though, that permanently becomes the type of B.
>
I guess this only works because any simple object has sizeof(T) char objects in its obj representation.
Otherwise the copy relies entirely on the aliasing rule. And since you ask for copying char objects, the copy function can decide to read the object T using a type compatible with char.
To have that not be UB you would need.transitive aliasing blessing from compatible-type to T by link over char.
On 2015–07–14, at 5:57 PM, David Krauss <pot...@gmail.com> wrote:Nothing is transitive. The bytes of object A are copied into storage buffer B.
On 2015–07–14, at 6:05 PM, 'Johannes Schaub' via ISO C++ Standard - Discussion <std-dis...@isocpp.org> wrote:To have that not be UB you would need.transitive aliasing blessing from compatible-type to T by link over char.
union String
{
char as_array[sizeof(int)];
int as_int;
};
String s;
memcpy(&s.as_array, "12345678", sizeof(int));
int & i = reinterpret_cast<int&>(s.as_array);
read(i);
On 2015–07–14, at 8:00 PM, Andrzej Krzemieński <akrz...@gmail.com> wrote:
W dniu wtorek, 14 lipca 2015 11:47:39 UTC+2 użytkownik David Krauss napisał:You can pun to character types with reinterpret_cast. Other types require something like memcpy, which works because it treats each of the two objects as a character sequence. Anything that behaves that way is sufficient, though, including std::copy<char const*, char*>.
Does this provision work only one way (from type T to char[])? Or is it also possible to reinterpret_cast from char[]?
It looks like a "safe" use of reinterpret_cast is to temporarily cast value v (of type T) to some other type U, and later back to T. But is there any legal way in the Standard to observe an (properly aligned) array of characters as int? (because computing equality of integers appears to be faster than performing memcmp on the same region).
For instance, is it legal to use the same union in combination with reinterpret cast:
union String
{
char as_array[sizeof(int)];
int as_int;
};
String s;
memcpy(&s.as_array, "12345678", sizeof(int));
int & i = reinterpret_cast<int&>(s.as_array);
read(i);