Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: разбор массива данных в структуры.  (Прочитано 12255 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
4y4z
Участник

ru
Offline Offline
Младший саппорт


« : 05-05-2010 17:07 » 

На входе есть массив данных, в котором  последовательно идут пакеты разной длины. Размер пакета определяется заголовком - 4, 9, 15 байт. Правильно ли будет разбирать массив данных, заполняя структуры на основании этого самого размера? Или структура всегда должна иметь размер кратный WORD/DWORD? Если да, то с чем это связано? Связано ли это с выравниванием?
Записан

Ищу работу. (разработка/тестирование/отладка)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 06-05-2010 03:22 » new

4y4z, в чём заключается задача - разобрать уже существующий поток данных или сделать передачу такого потока для последующего приёма и разбора ?
Записан

Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 06-05-2010 05:57 » 

Структура не обязана иметь размер, кратный DWORD. Но по умолчанию обычно имеет, поскольку компилятор выравнивает относительные адреса полей по границе.
Соответственно, никто не мешает указать компилятору, чтобы он этого не делал - с помощью #pragma pack(1) - и структура будет иметь размер, в точности равный сумме размеров её частей.

Проблему с выравниванием легко получить на архитектурах, не позволяющих адресацию двойных слов по невыравненным адресам в памяти. Но это отдельные грабли Улыбаюсь
« Последнее редактирование: 06-05-2010 05:59 от Вад » Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 06-05-2010 06:02 » 

Обычно выравнивание по байтовым границам не требуется, т.к. это не согласуется с архитектурой процессора и может вызвать лишние обращения к памяти (которые в десятки-сотни раз замедляют выполнение команды). Исключения: физические структуры для хранения на диске и передачи по сети и особые случаи оптимизации (со знанием архитектуры процессора и особенностей работы кешей и памяти и своего алгоритма).
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
4y4z
Участник

ru
Offline Offline
Младший саппорт


« Ответ #4 : 10-05-2010 09:54 » 

Tc
4y4z, в чём заключается задача - разобрать уже существующий поток данных или сделать передачу такого потока для последующего приёма и разбора ?
Задача именно разобрать суещствующий поток данных.
По сети приходит пакет с целевыми данными. Есть шапка из 2 байт,указывающая размер на основании типа записи. Все что между ними это целевые данные. К примеру заголовок указывает что длина пакета 15 байт. Правильно ли расписать разбор этих 15 байт так:
struct full_entry{
            unsigned int entry_type:2;
            unsigned int sats_number:4;
            unsigned int gps_fix:1;
            unsigned int ext_data:1;
            unsigned int speed:7;
            unsigned int unused_data:3;
            unsigned int utc_time:30;
            unsigned int xpos:24;
            unsigned int ypos:24;
            unsigned int zpos:24;
                  
         
         };
Записан

Ищу работу. (разработка/тестирование/отладка)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 10-05-2010 12:06 » 

4y4z, тогда выравнивание зависит от передающего: если оно там есть, то тебе нужно такое же выставить. Если посмотреть это негде - вычисли экспериментально Улыбаюсь

Но, судя по тому, что везде тип unsigned int , выравнивание будет 4 байта (обычно - по умолчанию)
Записан

RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 10-05-2010 16:52 » 

4y4z, такая структура скомпилируется в 5 unsigned int (20 байт), т.к. битовое поле не может быть в двух числах.

У GCC есть соотв. атрибут для борьбы с этим: __attribute__ ((packed))
С ним структура имеет размер 15 байт.

Возможно и у VC есть что-то подобное.
« Последнее редактирование: 10-05-2010 17:21 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
4y4z
Участник

ru
Offline Offline
Младший саппорт


« Ответ #7 : 10-05-2010 18:10 » 

4y4z, тогда выравнивание зависит от передающего: если оно там есть, то тебе нужно такое же выставить. Если посмотреть это негде - вычисли экспериментально Улыбаюсь

Но, судя по тому, что везде тип unsigned int , выравнивание будет 4 байта (обычно - по умолчанию)

Сделаю это экспериментально: uint я выставил сам, поскольку структуру писал на основе спецификации, где про размер мало что есть.
Записан

Ищу работу. (разработка/тестирование/отладка)
4y4z
Участник

ru
Offline Offline
Младший саппорт


« Ответ #8 : 10-05-2010 18:12 » 

4y4z, такая структура скомпилируется в 5 unsigned int (20 байт), т.к. битовое поле не может быть в двух числах.

У GCC есть соотв. атрибут для борьбы с этим: __attribute__ ((packed))
С ним структура имеет размер 15 байт.

Возможно и у VC есть что-то подобное.
Есть #pragma по-моему как раз для этих целей, но проект под *nix, так что буду пробовать с твоим вариантом.
Записан

Ищу работу. (разработка/тестирование/отладка)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 10-05-2010 18:40 » 

4y4z, есть еще один нюанс - порядок байт и порядок компоновки бит. Физическое представление и описание на Си могут различаться.

Код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct full_entry
{
    unsigned int entry_type:2;
    unsigned int sats_number:4;
    unsigned int gps_fix:1;
    unsigned int ext_data:1;
    unsigned int speed:7;
    unsigned int unused_data:3;
    unsigned int utc_time:30;
    unsigned int xpos:24;
    unsigned int ypos:24;
    unsigned int zpos:24;
} __attribute__ ((packed));

int main()
{
    struct full_entry t;
    unsigned char *p;
    int n, b;

    printf("Size: %u\n", sizeof(struct full_entry));

    memset((void*)&t, 0, sizeof(struct full_entry));
    t.entry_type = 3;
    t.gps_fix = 1;
    t.speed = 0x7f;
    t.utc_time = 0x3fAAAAff;
    t.ypos = 0xAAff55;

    p = (unsigned char*)(void*)&t;
    printf("Bits:\n     7 6 5 4 3 2 1 0\n");

    for (n = 0; n < sizeof(struct full_entry); n++)
    {
        printf(" %02u:", n);

        for (b = 0; b < 8; b++)
            printf(" %u", 1 & (p[n] >> (7 - b)));

        printf(" (0x%02x)\n", p[n]);
    }

    printf("\n");

    return 0;
}

Код:
gcc -Wall -o t1 t1.c

Код:
Size: 15
Bits:
     7 6 5 4 3 2 1 0
 00: 0 1 0 0 0 0 1 1 (0x43)
 01: 0 1 1 1 1 1 1 1 (0x7f)
 02: 1 1 1 1 1 1 0 0 (0xfc)
 03: 1 0 1 0 1 0 1 1 (0xab)
 04: 1 0 1 0 1 0 1 0 (0xaa)
 05: 1 1 1 1 1 1 1 0 (0xfe)
 06: 0 0 0 0 0 0 0 0 (0x00)
 07: 0 0 0 0 0 0 0 0 (0x00)
 08: 0 0 0 0 0 0 0 0 (0x00)
 09: 0 1 0 1 0 1 0 1 (0x55)
 10: 1 1 1 1 1 1 1 1 (0xff)
 11: 1 0 1 0 1 0 1 0 (0xaa)
 12: 0 0 0 0 0 0 0 0 (0x00)
 13: 0 0 0 0 0 0 0 0 (0x00)
 14: 0 0 0 0 0 0 0 0 (0x00)

Посмотри на тестовые значения и как битовое число расположилось в памяти. Специально инициализировал поля через одно.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines