Позиция памяти элементов в союзе C / C ++

У меня есть союз в C, как это:

union AUnion {
struct CharBuf {
char *buf;
size_t len;
} charbuf;
uint8_t num;
double fp_num;
};

У меня вопрос, могу ли я гарантировать, что если дано следующее:

union AUnion u;

Тогда верно следующее:

&u == &u.num
&u == &u.fp_num
&u == &u.charbuf

Т.е. все они начинаются в начале сегмента памяти, где u хранится.

В случае этой C-программы, скомпилированной с gcc version 5.3.0 а также -std=c11 вышеизложенное верно:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

union AUnion {
struct CharBuf {
char *buf;
size_t len;
} charbuf;
uint8_t num;
double fp_num;
};

int main(void)
{
union AUnion u;
printf("%d\n", ((void*)&u) == ((void*)&u.charbuf));
printf("%d\n", ((void*)&u.charbuf) == ((void*)&u.num));
printf("%d\n", ((void*)&u.num) == ((void*)&u.fp_num));
}

Как это печатает:

1
1
1

Компиляция кода выше как C ++ 11 с тем же компилятором приводит к тому же выводу, что и компиляция C11.

Но это стандартизированное поведение? Это неопределенно? Могу ли я рассчитывать на такое поведение с большинством компиляторов Си? Можно ли ожидать такого поведения и с компиляторами C ++?

15

Решение

В 6.7.2.1p16 стандарт C гарантирует, что:

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

Так что да, вы можете положиться на всех членов, начиная с unionадрес (обратите внимание, это то же самое для первого члена struct).

Стандарт C ++ включает аналогичное предложение в отношении стиля C (то есть только членов стиля C) unions /structс, потому что C ++ позволяет передавать unions-функции C, для которых требуется такая компоновка. Соответствующий раздел в стандарте C ++ — 9.5.


тем не мение, обратите внимание, что там может быть дополнение биты внутри стандартные простые типы (целые числа, числа с плавающей точкой). И их внутреннее может варьироваться (endianess). Вы также можете нарушать строгое правило алиасинга (С: эффективный тип).

13

Другие решения

Исходя из моего опыта, я бы сказал «да», хотя я проверил Стандарт C ++ 14 и это даже гарантирует это. (С ++ 11, скорее всего, будет иметь те же эффекты) Глава 9.5 гласит: All non-static data members of a union object have the same address

Таким образом, вы можете зависеть от этого поведения.

9

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector