Страница 150 из 386

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

Добавлено: Чт апр 18, 2013 16:36:48
HF_Cat
Есть вопрос по поводу локальных переменных. Освобождается ли ячейка ОЗУ, в которой была такая переменная, после завершения работы функции, в которой она была объявлена? Не разрастается ли объём ОЗУ при использовании большого количества лок. переменных?

И ещё, нужно ли при объявлении глоб. переменных в хедерах писать "typedef" в AVR Studio? Всё работает и без "typedef", но мало ли, решил переспросить.

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

Добавлено: Чт апр 18, 2013 16:39:19
Аlex
2 ibiza11

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

const screen_item_t *x[4];

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

Добавлено: Чт апр 18, 2013 18:02:56
ibiza11
Если объявить таким образом массив, то для каждого объявления переменной типа screen_t придется объявлять свой массив, причем каждый раз с новым именем. Так не пойдет. И я спрашивал про инициализацию, а не просто объявление.

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

Добавлено: Чт апр 18, 2013 18:08:55
FreshMan
чувстивителен ли язык Си к регистру ?
temp и TEMP - это разные переменные ?

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

Добавлено: Чт апр 18, 2013 18:13:30
Аlex
И я спрашивал про инициализацию, а не просто объявление
Дак у Вас не получится таким образом проинициализировать, не указав размер массива. Компилятору нужно знать размер типа.
Спойлер

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

typedef struct{
   const uint8_t *a;
   const uint8_t  b;
   const void    *c;
} screen_item_t;

typedef struct{
   const uint8_t *a;
   const void    *b;
   const uint8_t  c;
   const screen_item_t *x[4];
} screen_t;

const uint8_t a,b;

screen_item_t Item0 = {&a, 0, &b};
screen_item_t Item1 = {&a, 0, &b};
screen_item_t Item2 = {&a, 0, &b};
screen_item_t Item3 = {&a, 0, &b};

screen_t Screen0 = { &a,
                     &b,
                     4,
                     {&Item0, &Item1, &Item2, &Item3},
                     };
temp и TEMP - это разные переменные ?
Разные.

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

Добавлено: Чт апр 18, 2013 18:16:36
urry
Так не пойдет
По другому - никак - компилятор не знает, сколько выделить памяти. Еще в плюсах можно извернуться, в си - никак.

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

Добавлено: Чт апр 18, 2013 19:40:59
ploop
HF_Cat писал(а):Есть вопрос по поводу локальных переменных. Освобождается ли ячейка ОЗУ, в которой была такая переменная, после завершения работы функции, в которой она была объявлена? Не разрастается ли объём ОЗУ при использовании большого количества лок. переменных?
Освобождается. Это задача компилятора.

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

Добавлено: Чт апр 18, 2013 21:13:21
ibiza11
по задумке каждая переменная типа screen_t должна содержать свое количество указателей на переменные типа screen_item_t. может тогда как-то отделить определение структуры от определения размера массива? может подскажете как вместо массива указателей использовать указатель на массив указателей?

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

Добавлено: Чт апр 18, 2013 21:42:26
vitalik_1984
FreshMan писал(а):чувстивителен ли язык Си к регистру ?
temp и TEMP - это разные переменные ?
:wink: Пропиши, скомпилируй и узнаешь. Такие мелочи еще в начале книжки по Си написано, даже если и не написано можно легко проверить самому.

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

Добавлено: Чт апр 18, 2013 22:23:40
Аlex
ibiza11 писал(а):по задумке каждая переменная типа screen_t должна содержать свое количество указателей на переменные типа screen_item_t. может тогда как-то отделить определение структуры от определения размера массива? может подскажете как вместо массива указателей использовать указатель на массив указателей?
Можно хранить не массив указателей, а указатель на первый элемент и размер.
Спойлер

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

typedef struct{
    uint8_t   *a;
    uint8_t   b;
    void      *c;
}screen_item_t;

typedef struct{
    screen_item_t   *p;
    uint8_t         size;
}screen_t;


uint8_t a, b, c, d, e, f, g, h;

screen_item_t   Items[] ={
    {&a, 0, &b},
    {&c, 0, &d},
    {&e, 0, &f},
    {&g, 0, &h},
};

screen_t    Screen0 = {
    Items,
    sizeof(Items)/sizeof(Items[0])
};


//*******************************************************//
void main (void){
uint8_t         i;
screen_item_t   *p_scr;

for(i=0; i<Screen0.size; i++){      // Обращаемся ко всем элементам Items[]
    p_scr=(Screen0.p)+i;
    *(uint8_t*)(p_scr->a)=i+1;      // Через указатели, находящиеся в Items
    *(uint8_t*)(p_scr->c)=i+11;     // меняем значения переменных a...h
}


while(1);
}
//*******************************************************//
СпойлерИзображение
scr.JPG
(274.23 КБ) 294 скачивания

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

Добавлено: Пт апр 19, 2013 08:24:33
ibiza11
Спасибо за советы. Попробую применить. :beer:

PS
Сделал вот так:
Спойлер

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

#define com1(a,b)             a##b
#define com(a,b)              com1(a,b)


typedef struct{                  /* Тип "Пункт меню" */
   const uint8_t *pText;         /* Текст пункта */
   const action_t Action;        /* Код действия, выполняемого при нажатии ОК на этом пункте меню*/
   const void    *pChildScreen;  /* Указатель на следующий "Экран меню" при нажатии ОК*/
} item_t;

typedef struct{                  /* Тип "Экран меню" */
   const uint8_t *pHeader;       /* Заголовок экрана */
   const void    *pParentScreen; /* Указатель на предыдущий "Экран меню" при нажатии "Назад" */
   const uint8_t  ItemsOnScreen; /* Кол-во элементов "Пункт меню" на экране */
   const item_t  **pItemsArray;  /* Указатель на указатель на первый элемент массива */
} screen_t;

                                 /* Определение нового пункта меню */
#define NEW_ITEM(Name, Text, Action, Child)     \
extern screen_t Child;                          
item_t Name = {(const uint8_t*)&Text, Action, &Child}

                                 /* Определение нового эрана меню */
#define NEW_SCR(Name, Header, Parent, Items)                \
extern screen_t Parent;                                     
screen_t Name = { (const uint8_t *)&Header,                 
                   &Parent,                                 
                   sizeof(Items)/sizeof(com(Items,[0])),  
                   Items                                    
                   }

                                 /* Определение пустого указателя на экран */
#define NULL_SCR Null_Screen
screen_t Null_Screen = {(const uint8_t *)0, (const void*)0, (const uint8_t)0, (const item_t  **)0};


NEW_ITEM(Item0, "First item", 0, NULL_SCR);        /* Объявления новых пунктов меню */
NEW_ITEM(Item1, "Second item", 0, NULL_SCR);
NEW_ITEM(Item2, "Third item", 0, NULL_SCR);
NEW_ITEM(Item3, "Fourth item", 0, NULL_SCR);

item_t * Screen0Items[] = {&Item0, &Item1, &Item2, &Item3}; /* Объявление массива пунктов меню */

NEW_SCR(Screen0, "First screen", NULL_SCR, Screen0Items);   /* Объявление нового экрана меню */


static screen_t * CurrScreen;                      /* текущий экран и номер активного пункта меню */
static uint8_t    CurrItem; 
Применение:
Спойлер
#define ITEM_TEXT(ITEM_NUMBER)   (uint8_t*)((CurrScreen->pItemsArray)[ITEM_NUMBER])->pText
                                 // Получение текста любого пункта меню
#define ITEM_ACTION(ITEM_NUMBER) (action_t)((CurrScreen->pItemsArray)[ITEM_NUMBER])->Action
                                 // Получение выполняемого действия любого пункта меню
#define NEXT_SCREEN              (screen_t*)((CurrScreen->pItemsArray)[CurrItem])->pChildScreen
                                 // Получение указателя на следующий экран
#define PREVIOUS_SCREEN          (screen_t*)CurrScreen->pParentScreen
                                 // Получение указателя на предыдущий экран
#define CUR_HEADER               (uint8_t*)CurrScreen->pHeader
                                 // Получение заголовка текущего экрана
#define ITEMS_QUANTITY           (uint8_t)CurrScreen->ItemsOnScreen
                                 // Получение количества пунктов текущего экрана  
Итог: простое создание многомерных меню, с одновременным доступом к каждому свойству всех пунктов меню, находящихся на экране.
- При перемещении вверх или вниз просто инкрементируется или декрементируется CurrItem
- При выборе пункта проверяется действие, которое ассоциировано с пунктом, если оно не равно нулю, то выполняется действие (вызов функции), иначе происходит переход в дочернее меню NEXT_SCREEN (pChildScreen в item_t). Производится это простым присваиванием CurrScreen=NEXT_SCREEN
- При нажатии "Назад", аналогично CurrScreen = PREVIOUS_SCREEN, если он не равен NULL_SCR

Спасибо за помощь! :beer:

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

Добавлено: Пн апр 22, 2013 15:49:11
Real lev
Добрый день. Разбираюсь как прикрутить потдержку карт памяти и FAT32 от Чена, возник вопрос по синтаксису функций. Функция disk_ioctl в файле mmc.c(disko.c)
Спойлер#if _USE_IOCTL
DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
BYTE n, csd[16], *ptr = buff;
DWORD *dp, st, ed, csize;


if (pdrv) return RES_PARERR;

res = RES_ERROR;

if (cmd == CTRL_POWER) {
switch (ptr[0]) {
case 0: /* Sub control code (POWER_OFF) */
power_off(); /* Power off */
res = RES_OK;
break;
case 1: /* Sub control code (POWER_GET) */
ptr[1] = (BYTE)power_status();
res = RES_OK;
break;
default :
res = RES_PARERR;
}
}
......
}

return res;
}
#endif


указатель ptr типа BYTE(unsigned char) принимает значение указателя на воид buff. Компилятор от такой операции в шоке выдает ошибку. далее в функции case ptr выступает уже в роли массива. Как сделать такую конструкцию по правилам Си.

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

Добавлено: Пн апр 22, 2013 19:24:04
ibiza11
У Вас в коде лишняя закрывающая скобка.
а вообще в таких случаях используется приведение к типу.

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

BYTE n, csd[16], *ptr;
ptr = (BYTE *)buff;

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

Добавлено: Пн апр 22, 2013 21:29:04
shads
Вроде песня на Си льется мелодично, но иногда некоторый диссонанс вызывают варнинги, которые я еще не осознал......

Есть массив

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

char DataOutBuf[4]; 
с которым работаю в фоне и в прерывании, объявил его как

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

volatile char DataOutBuf[4];
в прерывании обращаюсь к нему так:

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

char* pDataOutBuf = DataOutBuf;
при этом, на эту строчку вылазит предупреждение

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

warning: initialisation discards qualifiers from pointer target type
Если volatile убрать, то варнинга нет, но обработка не правильно идет, что надо делать по другому, чтобы и волки сыты былы и овцы целы?????

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

Добавлено: Пн апр 22, 2013 21:42:30
Apparatchik
указатель тоже нужно объявить как volatile.

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

Добавлено: Пн апр 22, 2013 22:27:04
shads
Ух ты... так просто... Варнинг исчез.....
Только вот чето непонятно, какой смысл локальному указателю назначать volatile ?

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

Добавлено: Пн апр 22, 2013 22:29:41
Apparatchik
Если указатель указывает на объект, который "volatile", то и сам указатель нужно объявлять так же, компилятор же не совсем телепат, тоесть если вы уверены что ошибок в исполнении не будет, то необращайте внимания на варнинг.

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

Добавлено: Пн апр 22, 2013 22:29:52
ibiza11
в объявлении

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

volatile char* pDataOutBuf
не указатель volatile, а переменная, на которую он указывает.

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

Добавлено: Пн апр 22, 2013 22:43:03
Apparatchik
ibiza11 писал(а):не указатель volatile, а переменная, на которую он указывает.
ну я это имел ввиду :roll: выразился неправильно :wink:

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

Добавлено: Пн апр 22, 2013 22:45:49
shads
Apparatchik писал(а):если вы уверены что ошибок в исполнении не будет, то необращайте внимания на варнинг.
Да нет уж.....
лучше поставлю лишнее слово, чем будет мазолить глаза.....