Поиск C ясность Объединения

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;
   }

?

Любые указатели очень ценили (извините за игру слов),

5
задан timrau 14 August 2012 в 23:51
поделиться

6 ответов

если sizeof(GLfloat) == sizeof(float), то было выделено 4 плавающих числа.

flts[0], r и x будут относиться к одному и тому же фрагменту памяти здесь.

В союзе каждая переменная, объявленная в союзе, относится к одному и тому же фрагменту памяти.

Здесь у нас есть 3 переменные, 2 структуры и массив, и каждая из них начинается в одной и той же точке памяти.

5
ответ дан 18 December 2019 в 13:11
поделиться

Несколько вопросов :)

@Arkku прав насчет размера. Выравнивание тоже может сыграть свою роль, но, вероятно, не здесь.

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

Одна пара скобок предназначена для объединения, а другая - для инициализатора массива.

2
ответ дан 18 December 2019 в 13:11
поделиться

почему два набора фигурных скобок при использовании FltVector {{}}

Посмотрите на всю строку, FltVector fltVec1 = {{1.0f, 1.0f, 1.0f, 1.0f}}; Вы инициализируете четыре числа с плавающей запятой в , первую структуру в объединении. Как видно из полужирного «in», существует два уровня вложенности. Если бы уровень вложенности был еще глубже, у вас могло бы быть даже больше фигурных скобок.

1
ответ дан 18 December 2019 в 13:11
поделиться

Как было отмечено, код выделяет одну и ту же память, используя разные имена и типы данных. Иногда может быть удобно иметь возможность работать с именованными векторными компонентами (xyzw), в то же время имея возможность обрабатывать вектор как массив в другое время.

Однако похоже, что имена декартовой и радиальной структур поменялись местами. «r», «theta» и «phi» - общие названия радиальных координат, а не декартовых координат, которые обычно обозначаются как «x», «y» и «z».

Я думаю, что стоит отметить, что использование различных представлений не является строго совместимым со стандартами (но, вероятно, отлично работает во всех существующих реализациях C) по двум причинам:

  1. Чтение члена объединения, который не является последним написанным дает неопределенный результат. Однако любая разумная реализация вернет значение, хранящееся в этой памяти.
  2. Компилятор может добавлять отступы между членами структуры (по соображениям производительности), в то время как массивы никогда не дополняются. Впрочем, это вряд ли произойдет в этом случае на любом современном процессоре.
0
ответ дан 18 December 2019 в 13:11
поделиться

В вашем примере, если мы рассмотрим имя Из переменных, объединение, безусловно, не используется для доступа к одной и той же ячейке памяти через, скажем, 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);
}
1
ответ дан 18 December 2019 в 13:11
поделиться

Объединение позволяет вам "перерабатывать" одну и ту же область памяти для различных типов переменных. Обычно объединение занимает столько места, сколько занимает его самый большой член, в данном случае, вероятно, 4 float. Вы можете проверить с помощью sizeof.

В данном случае объединение, вероятно, используется для обеспечения 1) альтернативных имен для одних и тех же поплавков в структуре (например, x и r используют одну и ту же память) и 2) доступа к same четырем поплавкам в виде массива (например, x и flts[0] используют одну и ту же память). Иногда союзы используются в различных "хаках", обычно непортативных, для доступа к внутренним компонентам какого-либо типа данных, например, к отдельным байтам целого числа в машинном порядке.

5
ответ дан 18 December 2019 в 13:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: