Информация об изменениях

Сообщение Re[4]: Это UB ? от 16.07.2024 14:35

Изменено 16.07.2024 14:50 ononim

Re[4]: Это UB ?
vsb>https://en.cppreference.com/w/cpp/language/union
vsb>It is undefined behavior to read from the member of the union that wasn't most recently written
не люблю буквоедство, но давай тогда уж читать первоисточники, а не вольные пересказы:

If the member used to read the contents of a union object is not the same as the member last used to store a value in the
object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new
type as described in 6.2.6 (a process sometimes called “type punning”). This might be a trap representation

Как видим, в оригинале пишут, что данное UB стандартизовано в пункте 6.2.6
Ну а 6.2.6 просто рассказывает как там инты на биты ложатся .
Конкретное UB там описано лишь для случаев когда пишешь в переменную внутри union'а, то значения байтов которые не относятся к этой переменной становятся unspecified.

7 When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.
8 Where an operator is applied to a value that has more than one object representation, which object representation is used shall not affect the value of the result.52) Where a value is stored in an object using a type that has more than one object representation for that value, it is unspecified which representation is used, but a trap representation shall not be generated.

ну то есть это даже весьма гуманное UB, оно программисту в чай яду не подсыпет.
Есть пока один тонкий момент — пока ведь непонятно в каких байтах юниона располагаются его поля, но это вполне конкретизируется здесь:

The size of a union is sufficient to contain the largest of its members. The value of at most one of the members can be stored in a union object at any time. A pointer to a union object, suitably converted, points to each of its members (or if a member is a bitfield, then to the unit in which it resides), and vice versa.

Итак, факт того что указатель на union == указателю на любой его член де факто означает что они там все в его начале тусят.

Но к этому надо добавить type aliasing rules, это отдельная история, но как T4r4sB написал — char * и void * из них исключены.
Re[4]: Это UB ?
vsb>https://en.cppreference.com/w/cpp/language/union
vsb>It is undefined behavior to read from the member of the union that wasn't most recently written
не люблю буквоедство, но давай тогда уж читать первоисточники, а не вольные пересказы:

If the member used to read the contents of a union object is not the same as the member last used to store a value in the
object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new
type as described in 6.2.6 (a process sometimes called “type punning”). This might be a trap representation

Как видим, в оригинале пишут, что данное UB стандартизовано в пункте 6.2.6
Ну а 6.2.6 просто рассказывает как там инты на биты ложатся .
Конкретное UB там описано лишь для случаев когда пишешь в переменную внутри union'а, то значения байтов которые не относятся к этой переменной становятся unspecified.

6 When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values.51) The value of a structure or union object is never a trap representation, even though the value of a member of the structure or union object may be a trap representation.
7 When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.

ну то есть это даже весьма гуманное UB, оно программисту в чай яду не подсыпет.
Есть пока один тонкий момент — пока ведь непонятно в каких байтах юниона располагаются его поля, но это вполне конкретизируется здесь:

The size of a union is sufficient to contain the largest of its members. The value of at most one of the members can be stored in a union object at any time. A pointer to a union object, suitably converted, points to each of its members (or if a member is a bitfield, then to the unit in which it resides), and vice versa.

Итак, факт того что указатель на union == указателю на любой его член де факто означает что они там все в его начале тусят.

Но к этому надо добавить type aliasing rules, это отдельная история, но как T4r4sB написал — char * и void * из них исключены.