|
безымянные struct и union, WinAVR |
|
|
|
Jul 29 2010, 10:42
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
Цитата(dimka76 @ Jul 29 2010, 14:30)  Код union{ uint8_t id; int *num; }; Вы пытаетесь объединить 16-ти битную переменную и 8-битную. Указатель в памяти занимает два байта. вы не открыли америку - это как раз то, чего я и добиваюсь  инициализирую я, как вы можете видеть, или поле id, или поле num - но не оба одновременно. и использую я их так же исключительно по одному - в зависимости от контекста. кстати, оба этих поля инициализируются нормально, вопрос в другом - почему следующая структура в юнионе не инициализируется?!
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
|
Jul 29 2010, 11:32
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(ARV @ Jul 29 2010, 12:35)  Жаль, что все знатоки Си, которых тут немало, не желают подсказать, в чем я не прав, и объяснить, как следует поступить... если компилятор описание структуры считает корректным, если доступ к полям происходит - что не так с инициализацией? Ну вот сразу так "С". Сами же сказали, что это расширение GNU, в C99 такого нет. Так что все претензии к "знатокам GCC", а "знатоков С" трогать не надо. Кстати, чужая лень не нравится, но и самому лень было поместить в сообщении минимальный компилирующийся пример, чтобы всякие Код typedef struct { uint8_t itemcount; menu_item_t items[]; } menu_t; не нужно было дописывать... На мой взгляд, причина проста. Пусть есть Код typedef union { char c; double d; } u_t; Её инициализировать вот так Код u_t foo = { 5.0 }; нельзя. Ну, можно, только результат будет эквивалентен Код u_t foo = { .c = (char)5.0 }; Т.е. при инициализации объединения без C99-возможности указания имён полей инициализируется всегда первое поле. В структуре menu_item_t охватывающий union не имеет имён для полей-структур и инициализация летит в первое поле-структуру, а в этой структуре ну таки нет элемента .cnt. Если переместить структуры в хвост объединения Код typedef struct { prog_char *text; uint8_t type; union{ _tm submenu; struct { union{ uint8_t id; int *num; }; func_ptr func; }; struct { uint8_t vcnt; uint8_t *vid; prog_char **var; }; }; } menu_item_t; то и первая структура уже не будет инициализироваться.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jul 29 2010, 12:09
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
А это стандарт такой в Си, что можно инициализировать только первый элемент в union. Об этом можно на RSDN спросить, там любят стандарт обсуждать/цитировать. А если делать универсальное, гибкое меню, то можно как-то так: Код struct ItemHeader { prog_char *text; uint8_t type; void *content; };
struct Type1Item { union { uint8_t id; int *num; }; void (*func); };
struct Type2Item { uint8_t vcnt; uint8_t *vid; prog_char **var; };
PROGMEM Type1Item Item1 = { 100, NULL };
PROGMEM Type2Item Item2 = { 50, NULL, NULL };
PROGMEM char m1[] = {"Hello"}; PROGMEM char m2[] = {"Hello2"};
PROGMEM ItemHeader mainmenu[] = { {m1, 0, &Item1}, {m2, 1, &Item2}, }; ЗЫ. компилировал в С++ режиме
Сообщение отредактировал neiver - Jul 29 2010, 12:11
|
|
|
|
|
Jul 29 2010, 12:29
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(ARV @ Jul 29 2010, 14:48)  я ведь инициализирую с ЯВНЫМ указанием имен полей!!! Полей. да не тех. Эти поля он ищет в первом элементе охватывающего объединения, так как имя поля этого объединения не указано. Ну когда допиливали GNU exts до неименованных полей, место с инициализацией union трогать почему-то не стали, оставили по стандарту. Точнее, одну фишку добавили - "union cast", пример из предыдущего моего сообщения можно переписать так Код typedef union { char c; double d; } u_t;
u_t foo = (u_t)5.0; и оно чудненько сообразит проинициализировать double-часть. Но в данном случае даже вместе с C99 compound literals оно не помогает, где-то задалбывается и литерал не считает константой (впрочем, кажется, по C99 compound literal есть отдельный неименованный временный объект, потому он и не рассматривается как констант а). Компилировать с -fms-extensions, нужно для отмеченных мест Код typedef struct { prog_char *text; uint8_t type; union outer { /* -fms-extensions */ struct simplei { /* -fms-extensions */ union{ uint8_t id; int *num; }; func_ptr func; }; struct vari { /* -fms-extensions */ uint8_t vcnt; uint8_t *vid; prog_char **var; }; _tm submenu; }; } menu_item_t;
typedef struct { uint8_t itemcount; menu_item_t items[]; } menu_t;
enum { i_simple, i_int, i_var, i_sub };
#define simple_item(t,i,f) {.text = t, .type = i_simple, (union outer)(struct simplei){{.id=i}, .func = f} } #define int_item(t,n,f) {.text = t, .type = i_int, (union outer)(struct simplei){{.num = n}, .func = f} } #define var_item(t,c,vi,v) {.text = t, .type = i_var, (union outer)(struct vari){.vcnt=0} } #define sub_item(t,s) {.text = t, .type = i_sub, {.submenu = s}} Цитата uni_2.c:53: error: initializer element is not constant uni_2.c:53: error: (near initialization for ‘mainmenu.items[0].<anonymous>’) и для остальных элементов то же самое
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jul 30 2010, 09:51
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(ReAl @ Jul 29 2010, 15:29)  Но в данном случае даже вместе с C99 compound literals оно не помогает Увы. compound literals удобны, но генерирующийся временный объект не даёт инициализировать статические данные, поэтому тут не проходит. Если бы не это, то прошло бы. А так выходит ошибка, аналогичная Код int i1 = 5; int i2 = i1; // error: initializer element is not constant А -fms-extensions нужен только для того, чтобы дать имена типам структур неименованных полей и само по себе оно работает. p.s. то, что на avrfreaks предложили — на мой взгляд, некрасиво. Хотя, конечно, "работать будет". Несколько "причесать" предложение с avrfreaks (как-то гарантировать одинаковость структур — неименованной и вспомогательной) это вот -fms-extensions таки поможет Код typedef struct { union{ uint8_t id; int *num; }; func_ptr func; } simple_t;
typedef struct { uint8_t vcnt; uint8_t *vid; prog_char **var; } var_t;
typedef struct { prog_char *text; uint8_t type; union { simple_t; // это неименованные для работы var_t; _tm submenu; // вспомогательные для инициализации simple_t simple_helper; // первая не нужна, но для однообразия пусть будет var_t var_helper; }; } menu_item_t; Но всё равно как-то… Хотя "будут, будут одинаковые структуры одинаково расположены", но "некрасиво".
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Jul 30 2010, 10:58
|

Профессионал
    
Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581

|
на avrfreaks в очередной раз посоветовали написать свой компилятор... я все-таки не пойму: это просто недоделка расширения Си или так и положено? написано, что это расширение "для совместимости с некоторыми другими компиляторами" - так вот, в других компиляторах (интересно, каких?) возможна инициализация произволно заданных полей безымянных юнионов ? я так понимаю, смысл всей этой заморочки в том, чтобы вместо var.struct1.union1.struct2.union2.field писать просто var.field - а все helper-ы и тому подобное (через указатели на произвольные области) - это совсем не то, так как если я поименую часть юнионов, то и обращаться к ним надо будет уже только через имя... раздразнили сначала коротким вариантом, а потом выясняется, что это полуобман... уж лучше б и не упоминали о такой возможности - не так обидно было бы...
--------------------
Я бы взял частями... но мне надо сразу.
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|