Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Доступ к полям структуры.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Oleg_IT
Переношу код из AVR Studio (WINAVR) в Keil.
Компилятор выдаёт предупреждение на объявление, на стоку с "};"

Код
………
        struct {
            unsigned char Bit1        : 1;
            unsigned char Bit2        : 1;
        };
………….

..\Test.h(37): warning: #40-D: expected an identifier
И потом выдаёт ошибку на использование этих полей. Лечится это заданием имени структуры, например "} A1;", что не удобно, для меня. В WINAVR, в MinGW, в Visual Studio такого нет, только в Keil. Может быть это стандарт С++, не проверял и всех тонкостей языка не знаю. Можно какими-нибудь флажками убрать эту особенность?
shmur
Приведите весь код, а то не понятно это внутри структуры, юниона или просто чистое объявление.
psL
компилятору непонятно, как вы собираетесь использовать эту анонимную структуру в дальнейшем.
SlavaG
можно попробовать так:
Код
struct {
  unsigned char Bit1_      : 1;
  unsigned char Bit2_      : 1;
} A1;
#define Bit1 A1.Bit1_
#define Bit2 A1.Bit2_
VAI
Для анонимных структур существует #pragma anon_unions.
Почитать можно в файле "....\Keil\ARM\Hlp\armcc.chm" или здесь http://www.keil.com/support/man/docs/armcc...ef_BCFBCFBF.htm
или здесь http://infocenter.arm.com/help/index.jsp?t...c/BCFBCFBF.html
MrYuran
Что-то я не понимаю, как эту структуру безымянную использовать.
enum - другое дело.
A. Fig Lee
typedef struct {
unsigned char Bit1 : 1;
unsigned char Bit2 : 1;
} tStruct;


tStruct str1;
tStruct str2;

void func1() {
str1.Bit1 = 0;
}
shmur
Возможно у топик стартера было что -то вроде:
Код
union uu {
        struct {
            unsigned char Bit1        : 1;
            unsigned char Bit2        : 1;
        };
        int v;
};

Но некоторые компиляторы не позволяют использовать безымянные структуры, возможно Кейл как раз один из таких компиляторов.
vassabi
Может я что-то не понимаю, но как вы в битовое поле длиной один бит хотите воткнуть char, т.е. 8 бит?
Согласно справочника по С, битовое поле может быть signed или unsigned.
Если вы хотите unsigned char, то наверное нужно хотябы длинну поля указать :8...
A. Fig Lee
Цитата(vassabi @ Aug 30 2013, 10:47) *
Может я что-то не понимаю, но как вы в битовое поле длиной один бит хотите воткнуть char, т.е. 8 бит?
Согласно справочника по С, битовое поле может быть signed или unsigned.
Если вы хотите unsigned char, то наверное нужно хотябы длинну поля указать :8...

Кто хочет? Я?
SSerge
Цитата(vassabi @ Aug 30 2013, 21:47) *
Может я что-то не понимаю, но как вы в битовое поле длиной один бит хотите воткнуть char, т.е. 8 бит?
Согласно справочника по С, битовое поле может быть signed или unsigned.
Если вы хотите unsigned char, то наверное нужно хотябы длинну поля указать :8...

Я правильно понял, что в Вашей версии С невозможны поля длиной меньше 8 бит?
vassabi
Цитата("SSerge")
Я правильно понял, что в Вашей версии С невозможны поля длиной меньше 8 бит?
Не правильно. Читайте внимательно.
Палыч
Цитата(vassabi @ Aug 30 2013, 18:47) *
Согласно справочника по С, битовое поле может быть signed или unsigned.

Согласно стандарта:
Цитата
A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed int, unsigned int, or some other implementation-defined type.

Транслятор Keil в данном случае считает тип signed/unsigned char как "other implementation-defined type".
KnightIgor
Цитата(Oleg_IT @ Aug 30 2013, 12:41) *
Компилятор выдаёт предупреждение на объявление, на стоку с "};"

Код
………
        struct {
            unsigned char Bit1        : 1;
            unsigned char Bit2        : 1;
        };
………….

..\Test.h(37): warning: #40-D: expected an identifier


Код
………
        struct mystruct_s {
            unsigned char Bit1        : 1;
            unsigned char Bit2        : 1;
        };

...
struct mystruct_s variable_a, variable_b;
...

variable_a.Bit1 = variable_b.Bit2;

………….

Oleg_IT
Цитата
Приведите весь код, а то не понятно это внутри структуры, юниона или просто чистое объявление.

Это заголовок IP
Код
typedef struct IP_Head_v4_tag {
        struct {
            unsigned char IHL        : 4;   // IHL - 5
            unsigned char Version    : 4;   // Version - 4
        };

       struct {
            unsigned char Prec       : 3;   // Precedence - 3
            unsigned char D          : 1;   // Delay Normal - 0
            unsigned char T          : 1;   // Throughput Normal - 0
            unsigned char R          : 1;   // Relibility Normal - 0
            unsigned char Res1       : 2;   // Reserved - 00
        };

    unsigned short TotalLen;                // Total Length
    unsigned short Identif;                 // Идентификатор - 0

        struct {
            unsigned short FragOffset: 13;  // Fragment Offset - 0
            unsigned char MF         : 1;   // Fragment - 0 = Last Fragment
            unsigned char DF         : 1;   // Fragment - 1 = Don't Fragment
            unsigned char Res2       : 1;   // Reserved - 0
        };
        struct {
            unsigned char TTL        : 8;   // Time to Live < 1
            unsigned char Prot       : 8;   // Protocol
        };
    unsigned short Checksum;            // Header Checksum
    IPADDRESS IP_SRC_Adr;               // Source Address
    IPADDRESS IP_DST_Adr;               // Destination Address
} IP_Head_v4;

Со всеми перечисленными компиляторами (WINAVR, MinGW, Visual Studio) анонимные битовые поля структур работают правильно.

Цитата
Для анонимных структур существует #pragma anon_unions.

Спасибо, проверю, а вдруг поможет.

Цитата
Что-то я не понимаю, как эту структуру безымянную использовать.

Например так
Код
IP_Head_v4 IP_H;
IP_H.IHL = 5;
Oleg_IT
VAI спасибо, #pragma anon_unions помогла.
pitt
Просто хочу, как бывший советский гражданин, дать несколько советов.
Когда имеете дело со структурами, особенно отображающими пакеты данных, не забывайте endianness(простите не знаю как по-русски). Кроме того, советую включать файл stdint.h и использовать типы int8_t, uint16_t и тому подобное- это существенно облегчает как понимание, так и переносимость кода.

Oleg_IT
Цитата(pitt @ Sep 3 2013, 16:54) *
Просто хочу, как бывший советский гражданин, дать несколько советов.
Когда имеете дело со структурами, особенно отображающими пакеты данных, не забывайте endianness(простите не знаю как по-русски). Кроме того, советую включать файл stdint.h и использовать типы int8_t, uint16_t и тому подобное- это существенно облегчает как понимание, так и переносимость кода.

Спасибо, учёл.
MrYuran
Цитата(pitt @ Sep 3 2013, 15:54) *
Просто хочу, как бывший советский гражданин, дать несколько советов.
Когда имеете дело со структурами, особенно отображающими пакеты данных, не забывайте endianness(простите не знаю как по-русски). Кроме того, советую включать файл stdint.h и использовать типы int8_t, uint16_t и тому подобное- это существенно облегчает как понимание, так и переносимость кода.

По-русски это будет эндианность sm.gif
А я вообще не рекомендую мапить протоколы на структуры, потому как нарвался однажды на грабельное поле, и связано это было с выравниванием.
alx.bilous
И какой в этом вообще смысл?

чем это бы отличалось если не использовать вложенную анонимную структуру вообще.
pitt
Цитата(MrYuran @ Sep 4 2013, 07:47) *
А я вообще не рекомендую мапить протоколы на структуры, потому как нарвался однажды на грабельное поле, и связано это было с выравниванием.

А вот это напрасно. Если кто-то упаковывается данные, то, скорее всего, кто-то будет распаковывать. Такие вещи хорошо включать в заголовочный файл, который используется с обеих сторон.
Выравнивание часто действительно может стать проблемой, но это другая тема. Особенно важно структурированность пакетов передачи и, по умолчанию, выравнивание побайтное. Подавляющее большинство компиляторов позволяют выравнивать так как надо заказчику. Методы могут быть различными.
aaarrr
Цитата(pitt @ Sep 5 2013, 00:42) *
А вот это напрасно. Если кто-то упаковывается данные, то, скорее всего, кто-то будет распаковывать.

Смотрим C99 Annex J - Portability issues:
Цитата
— The order of allocation of bit-fields within a unit (6.7.2.1).
— The alignment of non-bit-field members of structures (6.7.2.1). This should present
no problem unless binary data written by one implementation is read by another.

Вывод: использовать битовые поля при работе с внешними данными нельзя. Вообще нельзя.

Ну, добавим пару исключений:
- можно в рамках одной архитектуры и компилятора (что очевидно)
- можно в случае проверки корректности упаковки на этапе сборки
jcxz
Цитата(pitt @ Sep 5 2013, 02:42) *
А вот это напрасно. Если кто-то упаковывается данные, то, скорее всего, кто-то будет распаковывать. Такие вещи хорошо включать в заголовочный файл, который используется с обеих сторон.
Выравнивание часто действительно может стать проблемой, но это другая тема. Особенно важно структурированность пакетов передачи и, по умолчанию, выравнивание побайтное. Подавляющее большинство компиляторов позволяют выравнивать так как надо заказчику. Методы могут быть различными.

Можно и методы сделать одинаковыми для C++. Я делаю так:
CODE
struct u16p8 {
u8 bytes[2];
operator u16() const { return u16load(&bytes); }
u16p8 & operator =(u32 val) { u16save(&bytes, val); return *this; }
};
struct u32p8 {
u8 bytes[4];
operator u32() const { return u32load(&bytes); }
u32p8 & operator =(u32 val) { u32save(&bytes, val); return *this; }
};

где: u16load(), u16save(), u32load(), u32save() - макросы, определённые по-разному в соответствии с платформой.
Если для Cortex-M3 и x86 к примеру u16load() будет:
#define u16load(p) (*(u16 *)p)
то для ARM7/9:
#define u16load(p) (*(u8 *)(p) | (u16)((u8 *)(p))[1] << 8)
Таким образом я совершенно свободно перетаскиваю структуры, описывающие пакованные структуры, между разными платформами.
Это очень полезно когда пишешь firmware и тут же пишешь клиентское ПО на PC (для этого устройства) и надо описать протокол взаимодействия - это можно делать в одном файле просто копируя его между двумя проектами.
Oleg_IT
Цитата(MrYuran @ Sep 4 2013, 15:47) *
По-русски это будет эндианность sm.gif
А я вообще не рекомендую мапить протоколы на структуры, потому как нарвался однажды на грабельное поле, и связано это было с выравниванием.

Я эту "проблему" решаю так
Код
#pragma push
#pragma pack(1)
……………………
#pragma pop

Предпочитаю структуры, нагляднее. Встречал код, где данные в выходной массив просто по смещениям вписываются. Мне не нравится. Вообще - на вкус и цвет, главное что бы работало и правильноsm.gif.
jcxz
Цитата(Oleg_IT @ Sep 5 2013, 16:35) *
Я эту "проблему" решаю так
...

Лучше:
#pragma pack(push, 1)
#pragma pack(pop)
Но только это к сожалению не во всех компиляторах работает.
pitt
Практически каждый компилятор/процессор имеет своё решение. Мои советы не имеют конкретной привязки, это более вопрос стиля, подхода, школы, если хотите. А не хотите - не надо. Для меня это АБСОЛЮТНАЯ необходимость и, по-этому, я ищу и пока всегда находил способы, как её добиться для всех комбинаций, которые мне пришлось встречать. Если есть конкретный вопрос для конкретной архитектуры и компилятора буду рад попробовать помочь.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.