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

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> безымянные struct и union, WinAVR
ARV
сообщение Jul 29 2010, 10:42
Сообщение #16


Профессионал
*****

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



Цитата(dimka76 @ Jul 29 2010, 14:30) *
Код
union{
                uint8_t id;
                int        *num;
            };


Вы пытаетесь объединить 16-ти битную переменную и 8-битную. Указатель в памяти занимает два байта.

вы не открыли америку - это как раз то, чего я и добиваюсь smile.gif инициализирую я, как вы можете видеть, или поле id, или поле num - но не оба одновременно. и использую я их так же исключительно по одному - в зависимости от контекста. кстати, оба этих поля инициализируются нормально, вопрос в другом - почему следующая структура в юнионе не инициализируется?!


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 29 2010, 11:32
Сообщение #17


Нечётный пользователь.
******

Группа: Свой
Сообщений: 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;
то и первая структура уже не будет инициализироваться.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ARV
сообщение Jul 29 2010, 11:48
Сообщение #18


Профессионал
*****

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



до этого предположения я как бы дошел, но у меня закономерный вопрос: а какого, извините, амперсенда, компилятор понимает, что при обращении надо перебрать все имена полей - и перебирает!!! - а при инициализации надо ограничиваться только первыми? я ведь инициализирую с ЯВНЫМ указанием имен полей!!!


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
neiver
сообщение Jul 29 2010, 12:09
Сообщение #19


Местный
***

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 29 2010, 12:29
Сообщение #20


Нечётный пользователь.
******

Группа: Свой
Сообщений: 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>’)
и для остальных элементов то же самое


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ARV
сообщение Jul 30 2010, 04:20
Сообщение #21


Профессионал
*****

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



что-то не выходит каменный цветок и с -fms-extensions ...


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 30 2010, 09:51
Сообщение #22


Нечётный пользователь.
******

Группа: Свой
Сообщений: 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;


Но всё равно как-то… Хотя "будут, будут одинаковые структуры одинаково расположены", но "некрасиво".


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ARV
сообщение Jul 30 2010, 10:58
Сообщение #23


Профессионал
*****

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



на avrfreaks в очередной раз посоветовали написать свой компилятор... sad.gif
я все-таки не пойму: это просто недоделка расширения Си или так и положено? написано, что это расширение "для совместимости с некоторыми другими компиляторами" - так вот, в других компиляторах (интересно, каких?) возможна инициализация произволно заданных полей безымянных юнионов ?

я так понимаю, смысл всей этой заморочки в том, чтобы вместо var.struct1.union1.struct2.union2.field писать просто var.field - а все helper-ы и тому подобное (через указатели на произвольные области) - это совсем не то, так как если я поименую часть юнионов, то и обращаться к ним надо будет уже только через имя...
раздразнили сначала коротким вариантом, а потом выясняется, что это полуобман... уж лучше б и не упоминали о такой возможности - не так обидно было бы...


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
ARV
сообщение Jul 30 2010, 18:10
Сообщение #24


Профессионал
*****

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



все-таки на avrfreaks подали идею, как выкрутиться из положения... костыль, но вполне элегантный smile.gif делается еще один или сколько надо именованных юнионов с теми же самыми полями и инициализируются именно именованные юнионы, а последующее обращение ведется через безымянные smile.gif


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jul 30 2010, 18:21
Сообщение #25


Нечётный пользователь.
******

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



Цитата(ARV @ Jul 30 2010, 21:10) *
все-таки на avrfreaks подали идею, как выкрутиться из положения... костыль, но вполне элегантный smile.gif делается еще один или сколько надо именованных юнионов с теми же самыми полями и инициализируются именно именованные юнионы, а последующее обращение ведется через безымянные smile.gif

Ну да, я выше "причесать" (дать typedef-ы, чтобы не копировать структуры и иметь гарантированное совпадение безымянных для обращения и именованных для инициализации) именно об этом их предложении и написал:
http://electronix.ru/forum/index.php?s=&am...st&p=791927


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 20:01
Рейтинг@Mail.ru


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