Is type-punning through a union unspecified in C99, and has it become specified in C11?

Refresh

November 2018

Views

7.8k time

55

A number of answers for the Stack Overflow question Getting the IEEE Single-precision bits for a float suggest using a union structure for type punning (e.g.: turning the bits of a float into a uint32_t):

union {
    float f;
    uint32_t u;
} un;
un.f = your_float;
uint32_t target = un.u;

However, the value of the uint32_t member of the union appears to be unspecified according to the C99 standard (at least draft n1124), where section 6.2.6.1.7 states:

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.

At least one footnote of the C11 n1570 draft seems to imply that this is no longer the case (see footnote 95 in 6.5.2.3):

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.

However, the text to section 6.2.6.1.7 is the same in the C99 draft as in the C11 draft.

Is this behavior actually unspecified under C99? Has it become specified in C11? I realize that most compilers seem to support this, but it would be nice to know if it's specified in the standard, or just a very common extension.

4 answers

4

Это всегда было «ненадежным». Как уже отмечалось в сноске был добавлен в C99 через технический Corregendum. Она гласит следующее:

Если член используется для доступа к содержимому объекта союза не то же самое, как член последней используемому для сохранения значения в объекте, соответствующая часть объекта представления значения переинтерпретируются в качестве представления объекта в новом типе как описан в 6.2.6 (процесс, который иногда называют «тип каламбурным»). Это может быть ловушкой представление.

Однако, сноски указываются в предисловии как ненормативный:

Приложения D и F образуют нормативную часть этого стандарта; приложения А, В, С, Е, G, Н, I, J библиография, и индекс приведена только для информации. В соответствии с частью 3 Директив ИСО / МЭК, это предисловие, введение, примечания, сноски и примеры также только для информации .

То есть, в сносках не может запретить поведение; они должны прояснить только существующий текст. Это непопулярное мнение, но сноска приведенная выше на самом деле не может в связи с этим - нет такого поведения запрещенного в нормативном тексте. Действительно, есть детали, такие как 6.7.2.1:

... Значение не более одного из членов может быть сохранено в объекте союза в любое время

В сочетании с 6.5.2.3 (в отношении доступа членов профсоюза с оператором «»):

Значение является то, что от имени члена

Т.е. , если значение только одного элемента может быть сохранено, то значение другого члена не существует. Это подразумевает , что тип каламбурный через союз должен не быть возможными; доступа члена дает несуществующее значение. Тот же текст по- прежнему существует в документе C11.

Тем не менее, очевидно, что цель добавления сноски было позволить для типа-каламбуров; это просто, что комитет, казалось бы, нарушил правила на сносках, не содержащие нормативный текст. Чтобы принять сноску, вы действительно должны игнорировать раздел, который говорит, что сноски не являются нормативными, или иным образом пытаться понять, как интерпретировать нормативный текст таким образом, что поддерживает вывод сноски (который я попробовал, и не удалось, сделать).

В разделе вы процитировать:

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

... должен внимательно прочитать, хотя. «Байты представления объектов , которые не соответствуют этому члену » имеет в виду байтов за пределы размера элемента, который сам по себе не является проблемой для типа каламбуров (кроме того, что вы не можете считать , писать к члену профсоюза оставит «экстра» часть любого крупного члена нетронутая).

-1

Тем не менее, это, кажется, нарушают стандарт C99 (по крайней мере, проект n1124), где раздел 6.2.6.1.7 состояния некоторые вещи. Является ли такое поведение на самом деле не определено в соответствии с C99?

Нет, ты в порядке.

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

Это относится и к блокам данных различных размеров. То есть, если у вас есть:

union u
{
    float f;
    double d;
};

и присвоить что-то е, это изменило бы нижние 4 байта й, а верхние 4 байта будет находиться в неопределенном состоянии.

Профсоюзы существуют в первую очередь для типа каламбуров.

Wug
17

Исходная спецификация C99 оставила это не определена.

Одним из технических исправлений к C99 (TR2, я думаю) добавлено примечание 82, чтобы исправить это упущение:

Если член используется для доступа к содержимому объекта союза не то же самое, как член последней используемому для сохранения значения в объекте, соответствующая часть объекта представления значения переинтерпретируются в качестве представления объекта в новом типе как описан в 6.2.6 (процесс, который иногда называют «тип каламбурным»). Это может быть ловушкой представление.

Это примечание сохраняется в стандарте C11 (это примечание 95 в С11).

37

Поведение типа каламбуров с союзом изменилось с C89 до C99. Поведение в C99 такая же, как C11.

Как ГВП отметил в своем ответе, тип каламбурная допускается в C99 / C11. Неопределенное значение , которое может быть ловушкой для чтения , когда члены профсоюза имеют разного размера.

Была добавлена сноска в C99 после Clive DW Feather Дефект Report # 257 :

И, наконец, одно из изменений от C90 до C99 в том, чтобы удалить какие - либо ограничения на доступ к одному члену профсоюза , когда последний магазин был к другому. Обоснование было то , что поведение будет тогда зависеть от представлений значений. Так как эта точка часто неправильно, это вполне может быть стоит сделать это ясно в стандарте.

[...]

Для решения вопроса о «типа» каламбуров, присоединить новую сноску 78а к словам «имени члена» в 6.5.2.3 # 3: 78а Если член используется для доступа к содержимому объекта союза не то же самое, как член последнего используется для хранения значения в объекте, соответствующая часть объекта представления значения переинтерпретируется в качестве представления объекта в новом типе, как описано в 6.2.6 (процесс, который иногда называют «типа каламбурная»). Это может быть ловушкой представление.

Формулировка Clive DW перо было принято для технического исправления в ответе С Комитетом по Дефект Report # 283 .