Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Прорезались зубы
Аватара пользователя
Сообщения: 202
Зарегистрирован: Пн сен 26, 2011 13:48:25
Откуда: Харьков

Сообщение slavokhire5 »

Здравствуйте:) Нубский вопрос по Си :)
У меня есть задача - отображать на меню дисплея. каждому элементу меню соответствует своя переменная. меню на дисплей вывожу так:

Код: Выделить всё

lcd_str(0x80, &menu[menu_index]);
переменную вывожу так:

Код: Выделить всё

if(menu_index == 0) {lcd_var(var_0);}
else if(menu_index == 1) {lcd_var(var_1);}
....
и таких строк прилично. реально переменные названы более удобными именами :) как бы их так упаковать, чтобы можно было их передавать в функцию вывода на дисплей по номеру элемента меню, без всяких проверок, но при этом чтобы сохранялись удобные для меня имена этих переменных для других случаев. сделать упакованную структуру и обращаться к переменной для вывода по адресу + приращение? но это как-то сильно через попу)
Осилит дорогу идущий
--------------------------
Пишу на Си за еду
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

Господа коты. Есть вопрос по С++.

Имеем стандартный связанный список и некий класс под именем MyClass
Структура (элемент списка) типа такой:

Код: Выделить всё

typedef struct _tag_ListObject
{
    pListOpject next;
    pListObject prev;
    int listId;
    MyClass *myClass;
} ListObject, *pListObject;
Я создаю элемент списка и объект класса, выделяя память из кучи:

Код: Выделить всё

pListObject listObject = new ListObject;
listObject->myClass = new MyClass;
// и т.д.
Как корректно освободить память, если в дальнейшем нужно будет этот элемент удалить?
Сначала удалить объект класса и за тем элемент списка, или достаточно будет удалить только элемент списка?

Код: Выделить всё

delete listObject->myClass; // сносим объект класса MyClass
delete listObject; // сносим элемент списка
И вызовется ли при удалении объекта его деструктор, если вместо поля MyClass* в структуре ListObject, будет стоять указатель void*?

Код: Выделить всё

MyClass::~MyClass();
I am DX168B and this is my favourite forum on internet!
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Сначала удалить объект класса и за тем элемент списка, или достаточно будет удалить только элемент списка?
Удалять нужно всегда в обратном направлении созданию.
И вызовется ли при удалении объекта его деструктор, если вместо поля MyClass* в структуре ListObject, будет стоять указатель void*?
Даже если там будет не void, он всё равно не вызовется. Там же находится, всего-лишь, указатель на объект, а не сам объект. Т.е. какая-то циферка :)
С какой стати ему удалять объект по этому указателю. Может Вы его где уже скопировали и будете потом по нему удалять.
Но если никаких ссылок на этот объект не остаётся, то, само собой разумеется, нужно удалить объект по ссылке, а потом уже удалять её. Иначе потом не будет возможности "добраться" до него, и он так и останется валяться в куче. Пока какой-нибудь сборщик мусора не дойдёт до него...
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

Ну дык в С++ оператор delete - это не аналог Сишного free()
Мы же передаем оператору delete указатель на класс. То есть, передаем объект имеющий некий общий тип. (класс, а не массив)
А это значит, что оператор автоматом должен вызвать сначала MyClass::~MyClass() и и только потом free()
Если бы оператору передали обычный массив, то оператор вызвал бы только free()
Или я чего-то не понимаю?
I am DX168B and this is my favourite forum on internet!
Контактная информация:
Реклама
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

DX168B писал(а):Мы же передаем оператору delete указатель на класс.
Ну вот и вызывайте его, передавая указатель. У Вас вопрос то в другом - вызовется ли деструктор автоматом, при удалении ссылки (указателя) на класс. Ответ - нет, не вызовется. Т.к. Вы будете удалять из памяти всего-лишь указатель, а не сам объект.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

Я имел в виду на счет этого:
Alex писал(а): Даже если там будет не void, он всё равно не вызовется.
Когда статья в MSDN говорит совсем о другом.
MSDN писал(а): Если оператор delete используется для отмены выделения памяти объекту класса C++, то перед отменой выделения памяти объекта вызывается деструктор этого объекта (если у объекта имеется деструктор).
На счет void* я имел в виду это:

Код: Выделить всё

typedef struct _tag_ListObject
{
    pListOpject next;
    pListObject prev;
    int listId;
    void *listData;
} ListObject, *pListObject;
Интуиция подсказывает, что сносить объект в случае с void надо так:

Код: Выделить всё

pListObject listObject = ...... //находим нужную структуру и присваиваем ее адрес
...
MyClass *myClass = (MyClass*)listObject->listData;
delete myClass;
delete listObject;
 
UPD:
Ладно. Сам проверю.
I am DX168B and this is my favourite forum on internet!
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

я, конечно, в плюсах не силен, но по-моему, правильно будет так:

Код: Выделить всё

delete (myClass*)listObject->listData;
а еще правильнее вместо структуры ListObject делать класс ListObject, а в его деструкторе освобождать память из-под listData. кстати, если listData указывает на экземпляр какого-то класса, то и соответствующее поле должно иметь правильный тип - указатель на этот самый класс, а не void*

имхо, либо ООП, либо обычный Си, помесь всегда уродлива...
Последний раз редактировалось ARV Вс мар 15, 2015 19:17:45, всего редактировалось 2 раза.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

DX168B писал(а):Я имел в виду на счет этого:
Alex писал(а): Даже если там будет не void, он всё равно не вызовется.
Когда статья в MSDN говорит совсем о другом.
Значит я Вас не понял.
Думал, что речь идёт о необходимости применять delete к полю-указателю структуры, при освобождении памяти от этой структуры. Если удалять объект-структуру из памяти, то имеющийся в ней указатель на объект - не повод удалять этот объэкт из памяти. Вот о чём я говорил.
Что касается применение delete к указателю, в котором "пустота". Естественно деструктор вызовется, только вызовется хрен знает что, а не деструктор.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

ARV писал(а):а еще правильнее вместо структуры ListObject делать класс ListObject, а в его деструкторе освобождать память из-под listData. кстати, если listData указывает на экземпляр какого-то класса, то и соответствующее поле должно иметь правильный тип - указатель на этот самый класс, а не void*
Абсолютно солидарен.
Если есть структура, к которой привязан какой-то объект-класс, то в его конструкторе самое место для выделения памяти под этот объект, с присвоением указателю адреса этого объекта, а в деструкторе - место под удаление из памяти этого объекта.
Кстати, для справки, структура тоже может иметь конструктор и деструктор.
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

Alex, ARV я вас понял.
Естественно, лучше вместо void ставить указатель на объект. И list надо делать в виде класса. Я собственно, так и сделал.
Но если у меня 50 различных классов, которые должны работать в списках? Некоторые из них полиморфные.
Не городить же мне кучу классов list под все типы объектов?
Есть у меня одно тонкое место в программе, где в одном списке хранятся несколько объектов произвольного типа.
Это список объектов для рендеринга (привет OpenGL). Этот список постоянно прокручивается рендером
и вызывает переопределенную virtual функцию в каждом объекте. (они у меня наследуются от одного класса)
А в списке объекты различных типов. Кроме как через void я никак не смог организовать по другому.
Может фантазии не хватило у меня или сноровки?
I am DX168B and this is my favourite forum on internet!
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Если все классы наследуются од одного единственного, то проблем вообще не должно быть. На сколько мне известно, достаточно иметь указатель на тип родителя, а виртуальная функция будет вызываться уже того наследника, на которого указывает указатель. Получается, что тип void* тут без надобности.
ЗЫ: Могу ошибаться. В полюсах не силён.
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

Аlex
Точно. А я и забыл. У меня они сначала были разрознены и реализованы в виде отдельных классов. Затем, я их объединил
одним родительским, преследуя другие цели (наследование некоторых алгоритмов, чтобы не раздувать программу). А про рендеринг забыл. Спасибо за наводку. :)

Код: Выделить всё

    Parent *pParent = 0;
    Parent parent;
    ChildOne childOne;
    ChildTwo childTwo;

    parent.PrintInt();
    childOne.PrintInt();
    childTwo.PrintInt();

    pParent = &childOne;

    pParent->PrintInt();
PrintInt - виртуальная функция. Переопределяется в дочерних классах ChildOne и ChildTwo.
Результат:

Код: Выделить всё

Parent
ChildOne
ChildTwo
ChildOne
ЗЫ: Пишу программу анализа и визуализации данных со скриптингом на Lua и прочими плюшками.
Эдакая большая платформа для радиолюбительских и не только целей. Исключительно для себя.
Как только получится что-нибудь стоящее, исходники и готовый билд программы будут выложены на github.
I am DX168B and this is my favourite forum on internet!
Контактная информация:
Родился
Сообщения: 3
Зарегистрирован: Ср мар 18, 2015 22:18:43

Сообщение termoking »

Доброго времени суток формучанам. если кто сможет - помогите пожалуйста! я с Си не "мяу" ваще,(да и в английском не очень)!! и очень нужно разобраться с вычислением CRC. в файле два примера. первый очень хорошо описан в виде словесного алгоритма ( и мне очень просто по нему написать свою прогу, не на Си) а вот второй взят из документа на то устройство с которым и предполагается работать.
Вопрос а скорее просьба к знатокам - если возможно описать второй пример так же или примерно так как в первом примере!
очень прошу!!!
Вложения
Новый текстовый документ.txt
(8 байт) 145 скачиваний
ks0
Прорезались зубы
Аватара пользователя
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

Сообщение ks0 »

1. В файле у вас отображается только 8 букв: zb5gu3uc
2. Для расчета CRC есть готовые функции http://www.nongnu.org/avr-libc/user-man ... __crc.html
Родился
Сообщения: 3
Зарегистрирован: Ср мар 18, 2015 22:18:43

Сообщение termoking »

приношу свои извинения! с файлом я что то напутал!! исправил! суть в том что я не могу толком разобраться с "функцией" из оригинальной документации!
Вложения
Новый текстовый документ.txt
(6.8 КБ) 157 скачиваний
Встал на лапы
Аватара пользователя
Сообщения: 85
Зарегистрирован: Пт фев 20, 2015 23:00:15

Сообщение ГруСныКот »

termoking писал(а):приношу свои извинения! с файлом я что то напутал!! исправил! суть в том что я не могу толком разобраться с "функцией" из оригинальной документации!
Дык

Код: Выделить всё

	unsigned short CRC16(puchMsg, usDataLen) 
	unsigned char *puchMsg;
	unsigned short usDataLen; 
	{
	unsigned char uchCRCHi = 0xFF;
	unsigned char uchCRCLo = 0xFF; 
	while (usDataLen--)
	{
	uIndex = uchCRCHi 
 *puchMsg++; 
	uchCRCHi = uchCRCLo 
 auchCRCHi[uIndex]; 
	uchCRCLo = auchCRCLo[uIndex];
	} 
	return (uchCRCHi << 8 | uchCRCLo); 
	} 
это тоже самое, что и

Код: Выделить всё

unsigned short CRC16(puchMsg, usDataLen)
unsigned char *puchMsg ; /* the message to be CRC checksum */
unsigned short usDataLen ; /* The number of bytes in the message */
{
unsigned char uchCRCHi = 0xFF ; /* High CRC byte initialization */
unsigned char uchCRCLo = 0xFF ; /* Low CRC byte initialization */
unsigned uIndex ; /* CRC cycle index */
while (usDataLen--) /* Transmitted message buffer */
{
uIndex = uchCRCHi ^ *puchMsgg++ ; /* Calculate the CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex} ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
за исключением опечатки *puchMsgg и использования метасимвола ^ начала строки. :)
Еще uIndex не объявили в первом.

Вы, наверное, что-то опять напутали. 8)
Родился
Сообщения: 3
Зарегистрирован: Ср мар 18, 2015 22:18:43

Сообщение termoking »

А вот за это - ПРЕОГРОМНЕЙШЕЕ СПАСИБО!!! ГруСныКот!!
по скольку я в Си "не очень" , мягко говоря, вижу что очень похоже НО еще и из-за
той самой неточности (опечатка и так далее) не стал делать выводов а решил спросить
у когонибудь, чтоб уже на верняка было! так что еще раз СПАСИБО!!!
Друг Кота
Сообщения: 13796
Зарегистрирован: Чт сен 20, 2007 14:08:00

Сообщение kalobyte »

что такое интерфейс в контексте языка программирования?
#define DATA_PIN1 9
#define DATA_PIN2 10
#define DATA_PIN3 11
#define DATA_PIN4 12
CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];
CRGB leds3[NUM_LEDS];
CRGB leds4[NUM_LEDS];
FastLED.addLeds<WS2811, DATA_PIN1, RGB>(leds1, NUM_LEDS);
FastLED.addLeds<WS2811, DATA_PIN2, RGB>(leds2, NUM_LEDS);
FastLED.addLeds<WS2811, DATA_PIN3, RGB>(leds3, NUM_LEDS);
FastLED.addLeds<WS2811, DATA_PIN4, RGB>(leds4, NUM_LEDS);
вроде это еще называется template на плюсах

а еще я недавно узнал про замыкания
на хабре была статья как раз, где автор как и я был в непонятках от всего этого гавна, чтобы придумали быдлокодеры

а чего я пишу? сегодня еще раз подтвердилось, что я образно мыслящий и быдлотексты не воспринимаю
Замыкание (англ. closure) в программировании — функция, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой функции в окружающем коде и не являющиеся её параметрами. Говоря другим языком, замыкание — функция, которая ссылается на свободные переменные в своём контексте.
это для меня набор слов какой-то
и вот так 95% быдлокниг технических написаны быдлороботами

смотрел видеоурок по написанию сервера на шарпе для вебсокетов и там был этот интерфейс
ведущий так и сказал, что это типа херня и что такое вам знать не надо, тупо делайте как я
вот я в быдлодуине и делаю тупо по шаблону

вот решил спросить
тематические ответы только в форуме, в приват не пишите
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

kalobyte
Замыкание (англ. closure) в программировании — функция, в теле которой присутствуют ссылки на переменные, объявленные вне тела этой функции в окружающем коде и не являющиеся её параметрами. Говоря другим языком, замыкание — функция, которая ссылается на свободные переменные в своём контексте.
Здесь говорится от "глобальных переменных"
Пример:

Код: Выделить всё

int var1 = 0;

int GetVar1(void)
{
    return var1; // Возврат значения переменной, которая объявлена вне функций (объявлена глобальной)
}

int GetSumVar1(int a)
{
    return a + var1; // var1 доступна во всех функциях.
}
 
На счет шаблонов. Их назначение - отвязка методов и классов от типов оперируемыми данными.
Класс, описанный по шаблону один раз, может оперировать данными практически любого типа.
Однако, базовые правила операций с данными все равно надо соблюдать. К примеру, нельзя одну строку делить на другую.
Однако, этот же шаблон предоставит свободу выбора между float и int, не прибегая к модификации кода.
Я шаблонами не пользуюсь, так как не вижу необходимости ими пользоваться. С++ использую исключительно для
упрощения кода и некоторых удобств, что шаблоны в принципе не дадут.
I am DX168B and this is my favourite forum on internet!
Контактная информация:
Ответить

Вернуться в «Разные вопросы по МК»