Как долго, как ваша структура типа не имеет отступов, нет никакой явной поддержки для этого в стандарте , но можно предположить, что поддержка чего-то очень близкого к ней.
Учитывая тривиальным Copyable типа T
, что явно разрешено, чтобы скопировать его представление в массив char
(или unsigned char
) и обратно.
Нет необходимости хранить содержимое массива в самом массиве. Содержимое может храниться в файле и перечитываться при последующем выполнении программы. Или хранится в объекте другого типа, если только этот тип допускает это. Чтобы это сработало, реализации должны допускать представления memcpy
ing в объекты, если эти представления не возникли из объектов типа T
в этом же запуске.
В результате, по крайней мере,
int main() {
vec v = {1.9f, 2.5f, 3.1f};
float a[3];
assert(sizeof v == sizeof a);
{ char tmp[3 * sizeof(float)];
std::memcpy(tmp, &v, 3 * sizeof(float));
std::memcpy(a, tmp, 3 * sizeof(float)); }
assert(a[0] == v.x);
assert(a[1] == v.y);
assert(a[2] == v.z);
vec u;
{ char tmp[3 * sizeof(float)];
std::memcpy(tmp, a, 3 * sizeof(float));
std::memcpy(&u, tmp, 3 * sizeof(float)); }
assert(u.x == a[0]);
assert(u.y == a[1]);
assert(u.z == a[2]);
}
должен либо не на первом assert
, или передать. Для любого представления, где он потерпел неудачу, тривиально создать функцию, которая, как представляется, придумывает это точное представление в однозначно допустимых способах, поэтому она не должна терпеть неудачу.
Теперь, опуская tmp
, здесь немного в порядке.
std::memcpy
- это просто повторные присвоения отдельных байтов и могут быть явно указаны. Из семантики оператора =
следует, что для трех типов, подлежащих копированию, a = b;
и { auto tmp = b; a = tmp; }
эквивалентны. То же самое с a = b; c = d;
и { auto tmp1 = b; auto tmp2 = d; a = tmp1; c = tmp2; }
и так далее. Первый - это то, что делает прямой memcpy
, последний - это то, что два memcpy
с до tmp
do.
С другой стороны, разрешение на копирование в и из массива char
может считаться требующим фактического массива char
, а не только его функциональный эквивалент.
Лично я, вероятно, не стал бы беспокоиться об этом, если бы я не натолкнулся на реализацию, которая использует эту интерпретацию, но если вы хотите играть в нее безопасно, вы можете ввести такой временный массив и убедиться, что ваш компилятор сумел оптимизировать это прочь.
Связанный (или, возможно, дубликат): http://stackoverflow.com/questions/37211298/accessing-an-array-as-a-struct-vs-undefined-behavior – Barmar
@Barmar - та же проблема, которая обсуждалась в вопрос, который я связал. –
Они оба говорят, что это неопределенное поведение. Почему, по-вашему, ваше дело по-другому? – Barmar