Re[3]: Правильно ли используется выделение памяти и пользова
От: Андрей Тарасевич Беларусь  
Дата: 19.11.06 08:31
Оценка:
Здравствуйте, vis1979, Вы писали:

АТ>>Это, похоже, именно С...


V>Да, это С, компиляция производиться на Borland C++ 3.1


АТ>>Если это именно C, то

АТ>>
АТ>>...
АТ>>  struct TimerStruct* tempTimerEl = malloc(sizeof *tempTimerEl);
АТ>>...
АТ>>

АТ>>Т.е. во-первых, никакого приведения типа не надо, и, во-вторых, 'sizeof' лучше натравить на указатель-получатель, а не на тип.

V>Понятно, спасибо, это я учту, но вот что сказано в helpe на malloc

V>
V>     char *str;

V>     /* allocate memory for string */
V>     if ((str = (char *) malloc(10)) == NULL)
V>     {
V>        printf("Not enough memory to allocate buffer\n");
V>        exit(1);  /* terminate program if out of memory */
V>     }
V>


В стародавние времена в языке С не было указателей на 'void' и функция 'malloc' возвращала 'char*'. По этой причине в те времена было принято всегда применять приведение типа к результату 'malloc' (даже если нужен был именно 'char*'). Вот этот пример их help-а как раз и демонстирурует эту давно устаревшую манеру. Старинный пример забыли подправить. Или было просто лень.

Сейчас наоборот выполнять такое приведение типа весьма и весьма не рекомендуется. По причинам, описанным в моем соседнем сообщении.

V>то есть приведение типа явно указано, как я понимаю ошибки в моем описании нет,

V>и вы представили лишь улучшение или я не до конца что то понимаю?

Ошибки нет, есть избыточность. И потенциальная опасность.

АТ>>Не понятно почему тип возврата — 'void*', а не 'struct TimerStruct*'.

V> Да собственно и не знаю почему просто tempTimerEl это элемент списка, для которого
V>выделяется память и заполняются поля, далее возращается в качестве результата функции
V>чтобы потом по идентификатору tempTimerEl его можно было найти в списке и удалить
V>вот такой функцией unsigned char DeleteTimer(void * ID_Timer) опять же с типом void *

По прежнему не понятно, почему не сделана типизация...

V>то есть по сути TimerKLZ[i] используется в следующем виде DeleteTimer(TimerKLZ[i]);

V>на самом деле в качестве void* подразумевался просто возвращаемый адрес элемента
V>в принципе все работает и вроде стабильно, но посто закрались смутные сомнения
V>правильно ли я выделяю память для списка указателей на void в таком виде:

V>
V>void ** TimerKLZ;
 
V> if ((TimerKLZ= (void **) malloc(sizeof(void *)*CountKLZ))==NULL)
V> {
V>  return 0;
V> }
V>


Формально правильно, но опять же — в такой записи содержатся ненужные инварианты и избыточные приведения. Если завтра ты решишь перейти с типа 'void*' на какой-нибудь другой, тебе придется сделать исправления в трех местах: объявление 'TimerKLZ', приведение типа и "параметр" 'sizeof'. В моем варианте исправление пришлось бы делать только в первом месте а строчку с 'malloc' вообще исправлять бы не надо было.

АТ>>По-прежнему не понятно, почему массив именно 'void*'-ов...

V>вопрос а как мне объявить массив указателей на TimerStruct?
V>таким же образом? "struct TimerStruct ** TimerKLZ;" — ???

Да.

V>и потом выделение

V>
V> if ((TimerKLZ= (struct TimerStruct **) malloc(sizeof(struct TimerStruct *)*CountKLZ))==NULL)
V> {
V>  return 0;
V> }

V>


...
if ((TimerKLZ = malloc(CountKLZ * sizeof *TimerKLZ)) == NULL)
...
Best regards,
Андрей Тарасевич
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.