typedef union {
float flts[4];
struct {
GLfloat r;
GLfloat theta;
GLfloat phi;
GLfloat w;
};
struct {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
};
} FltVector;
Хорошо, таким образом, я думаю, что добираюсь, как использовать это, (или, это - то, как я видел, что это использовало), т.е.
FltVector fltVec1 = {{1.0f, 1.0f, 1.0f, 1.0f}};
float aaa = fltVec1.x;
etc.
Но я не действительно groking, сколько устройства хранения данных было объявлено объединением (4 плавания? 8 плаваний? 12 плаваний?), как? и почему? Также, почему два набора фигурных скобок при использовании FltVector {{}}?
Почему использование объединение вообще? Почему бы не..
struct FltVector {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat w;
}
?
Любые указатели очень ценили (извините за игру слов),
если sizeof(GLfloat) == sizeof(float)
, то было выделено 4 плавающих числа.
flts[0]
, r
и x
будут относиться к одному и тому же фрагменту памяти здесь.
В союзе каждая переменная, объявленная в союзе, относится к одному и тому же фрагменту памяти.
Здесь у нас есть 3 переменные, 2 структуры и массив, и каждая из них начинается в одной и той же точке памяти.
Несколько вопросов :)
@Arkku прав насчет размера. Выравнивание тоже может сыграть свою роль, но, вероятно, не здесь.
Причина этого в том, что в любой момент времени объединение содержит только одно из возможных значений. По этой причине обычно объединение в структуре размещается рядом с чем-то, что определяет, какое значение является допустимым (иногда его называют размеченным объединением или сеткой ).
Одна пара скобок предназначена для объединения, а другая - для инициализатора массива.
почему два набора фигурных скобок при использовании FltVector {{}}
Посмотрите на всю строку, FltVector fltVec1 = {{1.0f, 1.0f, 1.0f, 1.0f}};
Вы инициализируете четыре числа с плавающей запятой в , первую структуру в объединении. Как видно из полужирного «in», существует два уровня вложенности. Если бы уровень вложенности был еще глубже, у вас могло бы быть даже больше фигурных скобок.
Как было отмечено, код выделяет одну и ту же память, используя разные имена и типы данных. Иногда может быть удобно иметь возможность работать с именованными векторными компонентами (xyzw), в то же время имея возможность обрабатывать вектор как массив в другое время.
Однако похоже, что имена декартовой и радиальной структур поменялись местами. «r», «theta» и «phi» - общие названия радиальных координат, а не декартовых координат, которые обычно обозначаются как «x», «y» и «z».
Я думаю, что стоит отметить, что использование различных представлений не является строго совместимым со стандартами (но, вероятно, отлично работает во всех существующих реализациях C) по двум причинам:
В вашем примере, если мы рассмотрим имя Из переменных, объединение, безусловно, не используется для доступа к одной и той же ячейке памяти через, скажем, x и r (поскольку радиус и координата x не подходят), но чтобы пользователь оставил один и тот же аргумент для обоих. Гораздо проще установить x, y, z, w, когда вы используете декартовы координаты, и было бы неудобно использовать эти же имена для радиальных координат. И оба они проще, чем просто индексы массива. Вероятно, у вас также есть другой параметр, который указывает тип предоставленной координаты (декартова или радиальная). Таким образом, у вас будет размеченный союз, как их называет pdbartlett.
В этом случае двойной уровень фигурных скобок бесполезен, поскольку массив может быть инициализирован либо через массив (двойной уровень фигурных скобок), либо через одну из внутренних структур.
исправление : двойной уровень фигурных скобок позволяет избежать преобразования входных данных в GLFloats.
Последняя деталь: безымянные внутренние структуры не являются стандартом C, стандартный способ сделать что-то - дать имена внутренним структурам, как в
typedef union {
float flts[4];
struct {
float r;
float theta;
float phi;
float w;
} cartesian;
struct {
float x;
float y;
float z;
float w;
} radial;
} FltVector;
FltVector f = {1.0, 2.0, 3.0, 4.0 };
int main(int argc, char * argv[]){
printf("flts[0]=%f f.radial.r=%f f.cartesian.x=%f\n",
f.flts[0], f.radial.r, f.cartesian.x);
}
Объединение позволяет вам "перерабатывать" одну и ту же область памяти для различных типов переменных. Обычно объединение занимает столько места, сколько занимает его самый большой член, в данном случае, вероятно, 4 float. Вы можете проверить с помощью sizeof
.
В данном случае объединение, вероятно, используется для обеспечения 1) альтернативных имен для одних и тех же поплавков в структуре (например, x
и r
используют одну и ту же память) и 2) доступа к same четырем поплавкам в виде массива (например, x
и flts[0]
используют одну и ту же память). Иногда союзы используются в различных "хаках", обычно непортативных, для доступа к внутренним компонентам какого-либо типа данных, например, к отдельным байтам целого числа в машинном порядке.