LINUX.ORG.RU

C++: закрепить обращение к конкретному члену union'a


0

0

Во избежание выравнивания, структура объединена в унионе с массивом размера структуры (очень уж надо). Обращений к массиву не происходит, но к структуре все равно приходится обращаться в стиле union->struct.someprop, что сильно снижает читаемость. Есть ли метод закрепить доступ к конкретному члену юниона (очень желательно без макросов, по причине той же читаемости)?

anonymous

>> Во избежание выравнивания, структура объединена в унионе с массивом размера структуры (очень уж надо).

Немного оффтопика: можно по-подробнее по поводу этого? Как объединение в юнион структуры и массива влияет на выравнивание?

Deleted
()
Ответ на: комментарий от Deleted

>Немного оффтопика: можно по-подробнее по поводу этого? Как объединение >в юнион структуры и массива влияет на выравнивание? Оно его убивает :) Т.е. я рядом со структурой (размер которой может меняться из-за выравнивания ее членов) кладу чаровый массив размера суммы размеров членов структуры, который не выравнивается. Плохо объяснил, но оно работает.

anonymous
()
Ответ на: комментарий от dilmah

>у юниона тоже можно перегружать операторы. Например operator-> мдя, разбежался. Как оно будет объявляться? mystruct* operator->(){return this->mystruct;}?

anonymous
()

Вроде то, о чем вы пишете (union, а внутири struct и char[]) --- это "хак" в стиле Си, поэтому лучше макросом, а макрос в качестве параметра берет указатель на этот union. Дать макросу осмысленное имя и читаемость будет хорошая...

mky ★★★★★
()
Ответ на: комментарий от anonymous

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

#include <iostream>

using namespace std;

namespace
{

struct STest
{
	int i;
	char c;
	unsigned long int uli;
	size_t s;
	void *p;
	uint64_t ui64;
};

#define MIN_STRUCT_SIZE (sizeof(int) + sizeof(char) \
	+ sizeof(unsigned long int) + sizeof(size_t) + sizeof(void *) \
	+ sizeof(uint64_t))

union UTest
{
	STest s;
	char arr[MIN_STRUCT_SIZE];
};

}

int main()
{
	cout << MIN_STRUCT_SIZE << endl;
	cout << sizeof(STest) << endl;
	cout << sizeof(UTest) << endl;
	
	return 0;
}

Выдаёт:
37
40
40

Либо ваш хак не работает, либо я опять не понял как он должен работать =).

Deleted
()
Ответ на: комментарий от Deleted

а не проще структуру упаковать ? :)

для gcc

struct STest
{
	int i;
	char c;
	unsigned long int uli;
	size_t s;
	void *p;
	uint64_t ui64;
} __attribute__ ((packed));

для MSVC 

#pragma pack

alex_custov ★★★★★
()
Ответ на: комментарий от alex_custov

>> а не проще структуру упаковать ? :)

Для этого нужно под каждый компилятор костылёчек в коде делать.

Deleted
()
Ответ на: комментарий от Deleted

ну если предположить, что под Linux код будет компилироваться gcc, а под виндой либо mingw либо msvc, то костылька нужно только два. Это хотя бы будет работать, в отличие от непонятного метода с union.

Насколько я помню, icc тоже поддерживает __attribute__. У кого есть, было бы хорошо проверить.

alex_custov ★★★★★
()
Ответ на: комментарий от Deleted

> Для этого нужно под каждый компилятор костылёчек в коде делать.

Ну а если так:

struct UTest {
   unsigned char ach[37];

   unsigned GetUInt(int offset) {
      return (unsigned)((unsigned)ach[offset + 0] << 24 | (unsigned)ach[offset + 1] << 16 | (unsigned)ach[offset + 2] << 8 | (unsigned)ach[offset + 3]);
   }
};

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

andreyu ★★★★★
()
Ответ на: комментарий от Deleted

Хмм, у меня работает.

#include <cstdio> struct s{ int i1; int i2; float f; char c[3]; };

union u{ struct s; char arr[15]; //Размер массива - сумма размеров элементов структуры - 4*3+3=15 };

int main(){ printf("Int: %d\nFloat: %d\n",sizeof(int),sizeof(float)); printf("Size of struct: %d\nSize of union: %d\n",sizeof(s),sizeof(u)); }

Выдает:

Int: 4 Float: 4 Size of struct: 16 Size of union: 15

anonymous
()
Ответ на: комментарий от Deleted

Сорри.
Хмм, у меня работает.

#include <cstdio>
struct s{
int i1;
int i2;
float f;
char c[3];
};

union u{
struct s;
char arr[15]; //Размер массива - сумма размеров элементов структуры - 4*3+3=15
};

int main(){
printf("Int: %d\nFloat: %d\n",sizeof(int),sizeof(float));
printf("Size of struct: %d\nSize of union: %d\n",sizeof(s),sizeof(u));
}

Выдает:

Int: 4
Float: 4
Size of struct: 16
Size of union: 15

anonymous
()
Ответ на: комментарий от anonymous

>>union u{ struct s;

чудик, это forward declaration.

ты так попробуй:

#include <cstdio>

struct s{ int i1; int i2; float f; char c[3]; };

union u { s st; char arr[15]; };

int main(int, char **)
{
    printf("Int: %d\nFloat: %d\n",sizeof(int),sizeof(float));
    printf("Size of struct: %d\nSize of union: %d\n",sizeof(s),sizeof(u));

    return 0;
}

# g++ -o st st.cpp
# ./st
Int: 4
Float: 4
Size of struct: 16
Size of union: 16

alex_custov ★★★★★
()
Ответ на: комментарий от andreyu

>> Такой подход будет работать на любой архитектуре, если записывать значение вы будете таким же способом.

Тогда уж лучше класс с кучей get*()/set*() и методами serialize()/deserialize() =).

Deleted
()
Ответ на: комментарий от Deleted

ну #pragma pack работает в msvc и в gcc. Я таким способом всегда и делаю)

s0L
()
Ответ на: комментарий от alex_custov

Мряя...
*поменял девиз на "через тернии к терниям"*

Кстати, собственно по сабжу идеи у кого-нибудь есть?

anonymous
()

А может быть что-то вроде:

struct str {
        int a;
        int b;
};

union un { 
        struct str s;
        char chr[sizeof(struct str)];
#define get_a s.a
#define get_b s.b
};

int main(int argc, char *argv[])
{
        union un uni;

        uni.get_a = 5;
        uni.get_b = 6;

        printf("%d %d\n", uni.get_a, uni.get_b);
}


lv ★★
()
Ответ на: комментарий от lv

И да.. по-моему, если я правильно тебя понял, то тут макросы, в отличии от переопределения операции читабельность нисколько не ухудшат. Хотя это кто к чему привык, наверное..

lv ★★
()
Ответ на: комментарий от dilmah

Да, это предубеждение вы выкорчевали вовремя, потом было бы поздно. Я убрал эту бяку, теперь структура пакуется. Тогда прошу объяснить как переопределить ->. mystruct* operator->(){return &mystruct_union_member;} компилируется, но при попытке обращения через стрелку напрямую к члену структуры выдается 'has no member'. Капча mixing - пора завязывать с сишным стилем в плюсах :)

anonymous
()
Ответ на: комментарий от lv

Спасибо. Правда, все равно прийдется писать на обоих. Но раздельно.

anonymous
()
Ответ на: комментарий от anonymous

Собственно, не хочу начинать очередной круг Священной Войны, но все же вопрос такой:

А ЗАЧЕМ тебе упакованные структуры?

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> А ЗАЧЕМ тебе упакованные структуры?

Лень сериализацию писать, очевидно.

Legioner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.