Объединение в союз, и сложная матрица - PullRequest
0 голосов
/ 08 марта 2019

XMFLOAT4X4 использует объединение внутри объединения для определения матрицы, но когда я пытаюсь использовать один и тот же метод с дополнительным объединением и без него, я получаю различные результаты в шаблонах доступа.Я не уверен, что это происходит при инициализации союзов или где я могу ошибаться при реализации.В моем коде единственное объединение не работало, но теперь в этом коде двойное объединение не работает.Почему это?

#include <stdio.h>

typedef union{
    union{
        struct{float xx,xy,xz,xw, yx,yy,yz,yw, zx,zy,zz,zw, wx,wy,wz,ww;};
        float m[4][4];
    };
}Mat4DoubleUnion;

typedef union{
    struct{float xx,xy,xz,xw, yx,yy,yz,yw, zx,zy,zz,zw, wx,wy,wz,ww;};
    float m[4][4];
}Mat4SingleUnion;

int main(void){
    Mat4SingleUnion mat_single_1 = 
    {1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1};
    Mat4SingleUnion mat_single_2 = 
    {1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1};
    Mat4DoubleUnion mat_double_1 = 
    {1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1};
    Mat4DoubleUnion mat_double_2 = 
    {1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1};

    Mat4DoubleUnion out_double;
    Mat4SingleUnion out_single;
    for(unsigned i = 0; i < 4; ++i){
        for(unsigned j = 0; j < 4; ++j){
            out_double.m[i][j] = mat_double_1.m[i][j] + mat_double_2.m[i][j];
            out_single.m[i][j] = mat_single_1.m[i][j] + mat_single_2.m[i][j];
        }
        printf("Double Union\n");
        for(unsigned i = 0; i < 4; ++i){
            printf("[%f  %f  %f  %f]\n", out_double.m[i][0], out_double.m[i][1], out_double.m[i][2], out_double.m[i][3]);
        }
        printf("\n");
        printf("Single Union\n");
        for(unsigned i = 0; i < 4; ++i){
            printf("[%f  %f  %f  %f]\n", out_single.m[i][0], out_single.m[i][1], out_single.m[i][2], out_single.m[i][3]);
        }
        printf("\n");
    }


}

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

Double Union
[2.000000  0.000000  0.000000  0.000000]
[0.000000  -170141183460469231731687303715884105728.000000  0.000000  0.000000]
[0.000000  0.000000  0.000000  0.000000]
[304728612076653271699817077145600.000000  18030524136642386826155261952.000000  269154975309704986624.000000  73908519441581681410048.000000]

Single Union
[2.000000  0.000000  0.000000  0.000000]
[0.000000  0.000000  0.000000  0.000000]
[0.000000  0.000000  0.000000  0.000000]
[0.000000  0.000000  0.000000  0.000000]

Double Union
[2.000000  0.000000  0.000000  0.000000]
[0.000000  2.000000  0.000000  0.000000]
[0.000000  0.000000  0.000000  0.000000]
[304728612076653271699817077145600.000000  18030524136642386826155261952.000000  269154975309704986624.000000  73908519441581681410048.000000]

Single Union
[2.000000  0.000000  0.000000  0.000000]
[0.000000  2.000000  0.000000  0.000000]
[0.000000  0.000000  0.000000  0.000000]
[0.000000  0.000000  0.000000  0.000000]

Double Union
[2.000000  0.000000  0.000000  0.000000]
[0.000000  2.000000  0.000000  0.000000]
[0.000000  0.000000  2.000000  0.000000]
[304728612076653271699817077145600.000000  18030524136642386826155261952.000000  269154975309704986624.000000  73908519441581681410048.000000]

Single Union
[2.000000  0.000000  0.000000  0.000000]
[0.000000  2.000000  0.000000  0.000000]
[0.000000  0.000000  2.000000  0.000000]
[0.000000  0.000000  0.000000  0.000000]

Double Union
[2.000000  0.000000  0.000000  0.000000]
[0.000000  2.000000  0.000000  0.000000]
[0.000000  0.000000  2.000000  0.000000]
[0.000000  0.000000  0.000000  2.000000]

Single Union
[2.000000  0.000000  0.000000  0.000000]
[0.000000  2.000000  0.000000  0.000000]
[0.000000  0.000000  2.000000  0.000000]
[0.000000  0.000000  0.000000  2.000000]

1 Ответ

0 голосов
/ 08 марта 2019

Попробуйте изменить эти две строки.Это очень тонкое использование перед проблемой инициации.

Mat4DoubleUnion out_double; memset(&out_double, 0, sizeof(out_double));
Mat4SingleUnion out_single; memset(&out_single, 0, sizeof(out_single));

В каждом внешнем цикле вы инициируете только одну строку out_single и out_double, поэтому остальная часть строки является мусором.В последнем внешнем цикле все строки правильно инициализированы, вывод правильный.Я думаю, что непосвященное использование неопределенного поведения, поэтому ...

вы можете попробовать инструмент проверки памяти valgrind, в этом случае будет много информации:

valgrind --tool=memcheck ./a.out
...