Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - [решено] Запись значения в объединение

Ответить
Настройки темы
C/C++ - [решено] Запись значения в объединение

Аватара для Hector

Misanthrope


Сообщения: 474
Благодарности: 38


Конфигурация

Профиль | Отправить PM | Цитировать


По Си проходим тему объединения, возник вопрос, для того, чтобы ввести значение объединения, надо ли предварительно знать тип этого значения? т. е. можно ли делать так
Код: Выделить весь код
union mnz
{
  int chislo;
  char bukva;
};

union mnz u;
а потом
Код: Выделить весь код
u='g';
и значение объединения будет g, или можно только так
Код: Выделить весь код
u.bukva='g';
какое вообще преимущество даёт применение объединений, если можно, с примером?

-------
Information must be free!
Нет границ, есть только препятствия


Отправлено: 01:07, 18-11-2010

 

Ветеран


Сообщения: 3320
Благодарности: 916

Профиль | Отправить PM | Цитировать


Hector, нет нельзя. Нужно указать элемент объедения, которому присваивается значение -> u.bukva='g';.
У объединения нет такого понятия как значение, есть значение его элементов. Именно значение, а не значения. Программисту нужно следить за тем, с каким элементом сейчас работа в объединении.

union используется преимущественно для экономии памяти.
Так же в качестве возвращаемого параметра функции удобно использовать, как некий интерфейс: если функция будет возвращать новый тип, его достаточно будет указать в объединении.

Например,
возьмем код из второго поста этой темы Поиск текста в файлах
в функции WinMain из всего множества объявлена переменная wcl типа WNDCLASS (это структура) и переменная msg типа MSG (тоже структура). Особенности использования первой таковы, что нужда в ней отпадает (в данном примере в частности) сразу же после использовании в функции RegisterClass. Вторая же напротив, нужна до окончания программы. Было бы логично использовать не нужную больше переменной память, и объединения тут поможет.
Для этого объявляем нечто вроде
Код: Выделить весь код
	union sharMem
	{
		WNDCLASS wcl;
		MSG msg;
	} sM;
и в соответствии с правилами использования элементов объединения используем.
Вместо
Код: Выделить весь код
	wcl.style = 0;
	wcl.lpfnWndProc = WindowFunc;
	wcl.cbClsExtra = 0;
//...
if (!RegisterClass (&wcl))
//...
	while(GetMessage(&msg, NULL, 0, 0) > 0)
	{
		TranslateMessage (&msg);
//...
будет
Код: Выделить весь код
	sM.wcl.style = 0;
	sM.wcl.lpfnWndProc = WindowFunc;
	sM.wcl.cbClsExtra = 0;
//...
if (!RegisterClass (&sM.wcl))
//...
	while(GetMessage(&sM.msg, NULL, 0, 0) > 0)
	{
		TranslateMessage (&sM.msg);
//...

В примере выше использования union сэкономило 28 байт, которые не выделили для переменой типа MSG, так как последняя разместилась в памяти ранее занимаемой переменной типа WNDCLASS (это чуть больше 40 байт). Про такое использование в WinMain объединений поисковик ничего не нашёл. Совет использования его там вычитал в книге Юрова посвященной Ассемблеру.
Это сообщение посчитали полезным следующие участники:

Отправлено: 02:26, 18-11-2010 | #2



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

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для Hector

Misanthrope


Сообщения: 474
Благодарности: 38

Профиль | Отправить PM | Цитировать


хорошо, а существует способ проверить при выводе, какое сейчас значение у объединения, допустим мне нужно вывести значение u, но как узнать в данный момент там цифра (int) или буква (char)?

-------
Information must be free!
Нет границ, есть только препятствия


Отправлено: 02:47, 18-11-2010 | #3


Аватара для ganselo

Старожил


Сообщения: 232
Благодарности: 90

Профиль | Сайт | Отправить PM | Цитировать


А если так?
Код: Выделить весь код
#include <string.h>
#include <stdio.h>

union test
{
    int in;
    char ch;
};

union test t;

int main()
{
    memset(&t, 'g', sizeof(t) + sizeof(int));
    
    printf("%c", t.ch);
    return 0;
}

-------
К величайшему сожалению "история учит нас тому, что она ничему не учит".


Отправлено: 02:55, 18-11-2010 | #4


Аватара для Hector

Misanthrope


Сообщения: 474
Благодарности: 38

Профиль | Отправить PM | Цитировать


ganselo, не совсем понял, можно комментарии (только учусь )

-------
Information must be free!
Нет границ, есть только препятствия


Отправлено: 02:56, 18-11-2010 | #5


Ветеран


Сообщения: 3320
Благодарности: 916

Профиль | Отправить PM | Цитировать


Hector, мне такой не известен, но для мониторинга\отладки можно через printf "позванивать" содержимое элементов объединения - printf("chislo - %i\tbukva-%c", u.chislo, u.bukva); и по выводу ориентироваться. Но правильнее смотреть по коду, к какому элементу последний раз было присваивание.

ganselo, смущает строчка memset(&t, 'g', sizeof(t) + sizeof(int)); при установки памяти выйдем на sizeof(int)) за пределы объединения?
Размер объединения в данном случаи int (по наибольшему размеру типа элемента объединения).

Отправлено: 03:00, 18-11-2010 | #6


Аватара для Hector

Misanthrope


Сообщения: 474
Благодарности: 38

Профиль | Отправить PM | Цитировать


Цитата Admiral:
Но правильнее смотреть по коду, к какому элементу последний раз было присваивание »
есть такая задача:
Необходимо обеспечить выполнение следующих действий (операций):
1) ввод информации в массив структур;
2) просмотр на экране содержимого массива структур в виде таблицы;
3) одним из элементов структуры является объединение;
Исходные данные:
Меню
  • Название блюда
  • Стоимость блюда
  • Объединение
    • Калорийность блюда
    • Наличие полезных веществ

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

-------
Information must be free!
Нет границ, есть только препятствия


Отправлено: 05:10, 18-11-2010 | #7


Ветеран


Сообщения: 3320
Благодарности: 916

Профиль | Отправить PM | Цитировать


Hector в таком случаи в структуре нужно завести ещё одну переменную, определённую как enum, для того что б контролировать к какому полю объединения было обращение.
Код: Выделить весь код
enum PlatterKPD {CALORIE, UTILITY};

struct{
	PlatterKPD pKPD;
//...
	union
	{
		/*Калорийность блюда;
		Наличие полезных веществ;*/
	};
}PlatterInfo;
//...
//для ввода интересуемся: продукт только калориен или есть ещё полезные вещества?
//соответственно заполняем PlatterInfo.pKPD как CALORIE или UTILITY
switch(PlatterInfo.pKPD)
{
	case CALORIE: /*scanf(“%s”, &PlatterInfo.Калорийность блюда);*/ break;
	case UTULITY: /*scanf(“%s”, &PlatterInfo.Наличие полезных веществ);*/ break;
	case default:
}
//при выводе так же через switch выводим
Это сообщение посчитали полезным следующие участники:

Отправлено: 14:44, 18-11-2010 | #8



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - [решено] Запись значения в объединение

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
[решено] Отключенная учетная запись и запись с истекшим сроком действия. В чем разница? CaminoDeFlores Microsoft Windows NT/2000/2003 4 01-06-2009 09:30
C/C++ - Присвоение функции значения mrcnn Программирование и базы данных 4 07-11-2008 08:26
SNMP и значения счётчиков villimilli Microsoft Windows NT/2000/2003 0 05-10-2006 05:20
Значения параметров h00ligan Автоматическая установка Windows 2000/XP/2003 1 21-06-2005 12:23
Значения абривеатур Trojn Хочу все знать 11 21-05-2003 23:58




 
Переход