|
|
  |
Можно ли в typedef struct описать массив переменной длины, IAR, C, AVR |
|
|
|
Feb 20 2009, 09:52
|

Местный
  
Группа: Свой
Сообщений: 378
Регистрация: 10-09-07
Из: UKR/Voz
Пользователь №: 30 423

|
Есть некий протокол который пытаюсь описать структурой типа Код typedef struct TMainS { unsigned char Start; unsigned long Adata; unsigned int Bdata; unsigned char Cdata[var]; unsigned int Ddata; unsigned int Edata;
} T_MainS_Header; Подскажите как в таких случаях поступат если, Cdata имеет переменную длину. Перед присваиваем типов можно легко найти значение var. Интересует доступ к полям Ddata и Edata, после присваивания типа MainS->Ddata или MainS->Edata. Возможно ли такое решение, в книге по С такого ненашол, компилятор упорно ругается на Cdata, говорит что надо константа для var, и я с ним согласен, но есть ли другие решения ?
Сообщение отредактировал west329_ - Feb 20 2009, 09:57
|
|
|
|
|
Feb 20 2009, 10:04
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(west329_ @ Feb 20 2009, 13:52)  Подскажите как в таких случаях поступат если, Cdata имеет переменную длину. Стандартами языка С С89 и С99 массивы переменной длины не предусмотрены. 2 варианта для тебя навскидку: 1. Объвить Cdata фиксированного размера, заведомо большим, чем может быть по протоколу. 2. Объвить поле unsigned char *Cdata, а затем, когда var будет известно - динамически выделять/освобождать через malloc/free.
Причина редактирования: Удаление излишнего цитирования.
|
|
|
|
|
Feb 20 2009, 11:01
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(west329_ @ Feb 20 2009, 11:52)  Подскажите как в таких случаях поступат если, Cdata имеет переменную длину. В С массив неизвестной длины (фактически - нулевой) может располагаться только в конце структуры. В плюсах массивы переменной длины средствами языка невозможны. На С вы можете разбить вашу структуру на две - Header и Footer. В первой Start, Adata, Bdata, Cdata, во второй - Ddata, Edata. К Footer обращаетесь через указатель, который ставите на нужное место памяти, когда уже знаете значение var. При передаче можно разбить процедуру на три части - передача заголовка, передача Cdata, передача заключительной части.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 20 2009, 14:06
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Сергей Борщ @ Feb 20 2009, 16:01)  В С массив неизвестной длины (фактически - нулевой) может располагаться только в конце структуры. Дополню слова Сергея. В таком случае (объявление без явного указания размера) массив будет incompete array, а в структуре под него будет выделена лишь переменная под указатель. Так что, если вы попытаетесь определить размер такой структуры с помощью sizeof, то результат может отличаться от ожидаемого. Это следует помнить и учитывать заранее.
|
|
|
|
|
Feb 21 2009, 10:01
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(west329_ @ Feb 21 2009, 11:25)  Если забирать данные с Cdata через указатель, какой размерности должен быть указатель ?. Вопрос неверен в корне. В Вашем случае указатель имеет размерность 2 байта в любом случае, т.к. размер ОЗУ врядли более 64КБ. Тип указателя определяется типом данных на которые он ссылается и всё. Более нет никаких характеристик у указателей. Если он указывает на байты, то unsigned char*, если на слова то unsigned short*Если на константные данные ссылается: const unsigned char*. Если сам указатель должен быть константным: unsigned char* constЕсли указатель константный и ссылается на сонстанту: const unsigned char* constНу и ещё надо не забывать о volatile, если Ваш указатель ссылается на аппаратный регистр контроллера или область памяти, которая может использоваться (изменяться) в прерываниях то надо писать так: volatile unsigned char* p = &PIND;
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Feb 21 2009, 16:59
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(west329_ @ Feb 21 2009, 12:25)  Если забирать данные с Cdata через указатель, какой размерности должен быть указатель ?.
Предпологаю, что INT, но не утверждаю, исхожу из того, что массив имеет размерность до 400 байт, и если забирать вручную через инкремент в переменную, указатель будет возвращать по 1 байту масива или по 2 ?. Указатель должен быть такого размера, чтобы однозначно адресовать память и зависит от процессора.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|