реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Инициализация структуры. Что не так?, Обращаюсь к коллективному разуму
SasaVitebsk
сообщение Sep 6 2012, 11:59
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Написал симулятор и отладил в QT4. Всё работает, достаточно объёмный проект.
Начал переносить на целевую платформу в IAR.
Споткнулся на ровном месте. Хотелось бы решить "в лоб", так как по-другому очень большой кусок работы.
Помогите.
Есть объявление структуры:
Код
// хранится во флэши
typedef struct
{
  int8_t               *Index;         // Указатель на редактируемый параметр/ смещение для каналов
  uint16_t              Number;         // Число пунктов
  uint16_t                Ch;                // 0/ Указатель на канал
  uint8_t               *ItemName[];    // Указатели на имена пунктов
} RadioBtn_t;

Есть строки:
Код
uint8_t const    sFlowControlComport[3][9] = {"None","Hard","Xon/Xoff"};

Есть объявление:
Код
//***************************************************************
// @@ 1312. Управление потоком
RadioBtn_t rbtFlowControl =
{
    0,                                            // Указатель на редактируемое значение
    3,                                            // Всего 3 пункта,
    ((uint32_t)&ComSetting[0].flowcontrol- (uint32_t)ComSetting),    // flowcontrol
    {sFlowControlComport[NONE], sFlowControlComport[HARD], sFlowControlComport[SOFT]}
};

Qt компилирует правильно и никаких вопросов у него это не вызывает
У IAR ARM 6.4.02 возникает 2 ошибки
1 - в строке 4 структуры у него претензия, что это не константа, но на самом деле это смещение адресов и должно вычислятся на этапе компиляции. Не вижу здесь проблемы и QT тоже не видит. Как это объяснить IAR?
2 - IAR в строке 5 пишет: слишком много параметров инициализации. Честно говоря, тоже не вижу проблемы.
Понятно что я могу указать лишь только имя масива и смещаться на длину элемента, но здесь я привожу только частный случай. Есть места, где это разные строки произвольной длины, так что такой метод не предлагать. Хотелось бы поэкономить место. Не хотелось бы также создавать отдельный масив указателей - тоже + 4 байта на один радиобутон. Поскольку элементов очень много, то будет набегать. Ну и QT почемуто понимает меня и работает как нужно. Поэтому непонятно ...
Какие будут предложения?
Заранее благодарю всех откликнувшихся ...
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Sep 6 2012, 12:22
Сообщение #2


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата
uint8_t const sFlowControlComport[3][9] = {"None","Hard","Xon/Xoff"};


Обычно это несколько по-другому пишется, если имеются в виду константные строки.

uint8_t const* sFlowControlComport[3] = {"None","Hard","Xon/Xoff"};

По-моему, так.

Компилятор составит таблицу указателей на ascii-строки


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Sep 6 2012, 12:39
Сообщение #3


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



По поводу ошибки номер раз. Воспользуйтесь дефайном offsetof()

Он гораздо яснее для понимания задумки программера.

Цитата(SasaVitebsk)
Поскольку элементов очень много, то будет набегать. Ну и QT почемуто понимает меня и работает как нужно. Поэтому непонятно ...

Напоминает Борланд Билдер, препроцессор и sizeof sm.gif

Вопрос стоит как это должно быть по стандарту. С пояснением от какого года стандарт.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 6 2012, 13:08
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(GetSmart @ Sep 6 2012, 16:39) *
По поводу ошибки номер раз.

Спасибо огромное. Ошибку номер раз закрыли. cheers.gif

Цитата(MrYuran)
Обычно это несколько по-другому пишется, если имеются в виду константные строки.

Имеется ввиду именно это, но IAR не позволяет инициализировать двухмерный массив, если младшее измерение открыто. По-моему другие компиляторы тоже.
То есть Ваше объявление не проходит.
uint8_t const sFlowControlComport[3] = {"None","Hard","Xon/Xoff"};
Error[Pe144]: a value of type "char [5]" cannot be used to initialize an entity of type "unsigned char const [3]" E:\work\IAR C Proect\tm3\Source\var.c 86

Вот такое, естественно, пройдёт
uint8_t const sFlowControlComport[] = {"None"};
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Sep 6 2012, 13:21
Сообщение #5


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(SasaVitebsk @ Sep 6 2012, 17:08) *
Имеется ввиду именно это, но IAR не позволяет инициализировать двухмерный массив, если младшее измерение открыто. По-моему другие компиляторы тоже.
То есть Ваше объявление не проходит.

Он одномерный, содержит указатели на начала строк.
Звездочку возле const* забыли sm.gif


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
scifi
сообщение Sep 6 2012, 13:23
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(SasaVitebsk @ Sep 6 2012, 17:08) *
Имеется ввиду именно это, но IAR не позволяет инициализировать двухмерный массив, если младшее измерение открыто. По-моему другие компиляторы тоже.

Это массив указателей. Посмотрите внимательнее: там должна быть звёздочка. Ну и если строки не меняются, то const можно написать 2 раза:
Код
const char* const foobar[] = { "one", "two", "three" };
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 6 2012, 13:27
Сообщение #7


Гуру
******

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



QUOTE (SasaVitebsk @ Sep 6 2012, 16:08) *
То есть Ваше объявление не проходит.
uint8_t const sFlowControlComport[3] = {"None","Hard","Xon/Xoff"};
Error[Pe144]: a value of type "char [5]" cannot be used to initialize an entity of type "unsigned char const [3]" E:\work\IAR C Proect\tm3\Source\var.c 86
"Смешались в кучу кони, люди", uint8_t, char, указатели...
Вы хотите массив из трех указателей на строки символов, а объявляете массив из трех беззнаковых 8-битных чисел.
Попробуйте все же объявлять массив указателей, и указателей именно на char:
char const * const sFlowControlComport[3] = {"None","Hard","Xon/Xoff"};


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 7 2012, 05:54
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Спасибо большое. Что-то вчера, к концу рабочего дня мозги уже не работали.
Вариант "const uint8_t* const sFlowControlComport[3] = {"None","Hard","Xon/Xoff"};" работает, собственно как и мой первоначальный.
Проблема то не в этом.
Проблема в объявлении структуры

Код
// @@ 1312. Управление потоком
RadioBtn_t rbtFlowControl =
{
    0,                                            // Указатель на редактируемое значение
    3,                                            // Всего 3 пункта,
    offsetof(ComSetting_t,flowcontrol),            // flowcontrol
    {sFlowControlComport[NONE], sFlowControlComport[HARD], sFlowControlComport[SOFT]}
};

Error[Pe146]: too many initializer values E:\work\IAR C Proect\tm3\Source\MonoMenu\lcd_work.c 346
Объявление структуры - в посте выше.
Ещё раз отмечаю - QT скомпилировал и прекрасно работал
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Sep 7 2012, 06:03
Сообщение #9


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(SasaVitebsk @ Sep 7 2012, 09:54) *
Вариант "const uint8_t* const sFlowControlComport[3] = {"None","Hard","Xon/Xoff"};" работает, собственно как и мой первоначальный.

Вот и чудненько.
Код
// @@ 1312. Управление потоком
RadioBtn_t rbtFlowControl =
{
    0,                                            // Указатель на редактируемое значение
    3,                                            // Всего 3 пункта,
    offsetof(ComSetting_t,flowcontrol),            // flowcontrol
    sFlowControlComport[]
};



--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 7 2012, 06:18
Сообщение #10


неотягощённый злом
******

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



Код
typedef struct
{
  int8_t*            Index;
  uint16_t           Number;
  uint16_t           Ch;
  const char* const* ItemName;
} RadioBtn_t;

const char* const sFlowControlComport[] = {"None", "Hard", "Xon/Xoff"};

const RadioBtn_t btn =
{
    (void*)0,
    0,
    0,
    sFlowControlComport
};

int main(void)
{
    puts(btn.ItemName[0]);
    puts(btn.ItemName[1]);
    puts(btn.ItemName[2]);

    return (0);
}
output:
Код
None
Hard
Xon/Xoff


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
scifi
сообщение Sep 7 2012, 06:24
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Кстати, как-то не очень хорошо выглядит эта структура:
Код
typedef struct
{
  int8_t   *Index;
  uint16_t Number;
  uint16_t Ch;
  uint8_t  *ItemName[];
} RadioBtn_t;

В конце она содержит массив неопределённого размера.
Лучше применить указатель на массив строк:
Код
typedef struct
{
  int8_t   *Index;
  uint16_t Number;
  uint16_t Ch;
  char const * const *ItemName;
} RadioBtn_t;
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 7 2012, 07:38
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(scifi @ Sep 7 2012, 10:24) *
Кстати, как-то не очень хорошо выглядит эта структура:
В конце она содержит массив неопределённого размера.

Именно это я и хотел!
Я показал один вариант, когда у меня массив указателей, но в других элементах интерфейса, может быть просто несколько несвязанных указателей.
Если я укажу просто масив указателей, то дополнительные затраты - 1 указатель. Элементов много и набежит прилично.
Оно конечно не критично, но просто переписать придётся. Там где применены разрозменные строки, то надо добавить массив указателей.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 7 2012, 07:54
Сообщение #13


неотягощённый злом
******

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



Зато размер структуры RadioBtn_t будет значительно меньше (всего один указатель на массив строк вместо N указателей на каждую строку). ОЗУ экономится...
Это, я думаю, должно быть первично. Тем более, если вы говорите, что их у вас много набегает.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Sep 7 2012, 08:04
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



rolleyes.gif Я буду добиваться, чтобы всё во флэш легло. Это обычное графическое меню, для 128*64. И в озу ему делать нечего ... biggrin.gif
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 7 2012, 08:09
Сообщение #15


неотягощённый злом
******

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



Не выйдет. Нельзя в си инициализировать константу константой...
например так нельзя:
Код
const int x = 3;
const int y = x;  // никак, обидно:-(

и так нельзя:
Код
const RadioBtn_t rbtFlowControl =
{
    0,
    3,
    offsetof(ComSetting_t,flowcontrol),
    {sFlowControlComport[NONE], sFlowControlComport[HARD], sFlowControlComport[SOFT]}  // это невозможно при наличии const квалификатора у типа этой rbtFlowControl структуры.
};

разве что:
Код
typedef struct
{
  int8_t*     Index;
  uint16_t    Number;
  uint16_t    Ch;
  const char* ItemName[];
} RadioBtn_t;

const char sFlowControlComportNone[]    = "None";
const char sFlowControlComportHard[]    = "Hard";
const char sFlowControlComportXonXoff[] = "Xon/Xoff";

const RadioBtn_t btn =
{
    (void*)0,
    0,
    0,
    {
        sFlowControlComportNone,
        sFlowControlComportHard,
        sFlowControlComportXonXoff
    }
};
И keil и gcc (правда gcc только при включенной опции --pedantic) ругаются на сие, но по-разному:
Код
keil: main.c(26): error:  #146: too many initializer values
gcc: main.c:26:2: error: initialization of a flexible array member [-Werror=pedantic]

Думаю, что keil не прав, но от этого вам не легче. И переписать всё-же придётся чтобы был нормально переносимый код.
Я обычно когда сомневаюсь в чём-то (правда уже редко это бывает) сразу на разных компиляторах прогоняю тестики и делаю выводы о том что такое хорошо, а что такое плохо.
Безотносительно даже стандарта Си...
Вы кстати добавьте следующие ключи компиляции к gcc (если у вас он установлен) узнаете много нового о своих программах:-)
-std=c99
-pedantic
-Wall
-Wextra
-Werror


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 3rd August 2025 - 03:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01505 секунд с 7
ELECTRONIX ©2004-2016