Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Получить последовательность байтов из структуры


Автор: DanilSoldatov 30.4.2008, 09:14
Привет программистам!

Не мог бы мне кто-нить пояснить такую ситуацию (пишу на Си).
Мне нужно получить последовательность байтов из union SENDPRICE в массиве char page[50].

Объявление следующее:

struct TLVHADPrefix
{ 
  char  Protocol[3];
  char Version;
};  

struct TLVHAD
{ 
  struct TLVHADPrefix Prefix;
  char  WSCode[8];
  WORD OperCode;
  DWORD Len;
};

union SENDPRICE
{
    char page[50];
    
    struct 
    { 
      struct TLVHAD Header;
      WORD Tag;
          WORD Len;
          char  DATE[12];
    } var; 
}; 

Затем в теле функции я присваиваю значения членам структуры - члена union SENDPRICE:

        union SENDPRICE vTLV302; // Объявление 

        memcpy( vTLV302.var.Header.Prefix.Protocol, "TLV", 3 );

    vTLV302.var.Header.Prefix.Version = '1';
    
        memcpy( vTLV302.var.Header.WSCode, "00000022", 8 );

    vTLV302.var.Header.OperCode = 302;
    vTLV302.var.Header.Len = 13;
    
    vTLV302.var.Tag = 1;
    vTLV302.var.Len = 23;   
        memcpy( vTLV302.var.DATE, "444444444447", 12 );
    
и смотрю, что появилось в page[50], ожидая там увидеть всю эту последовательность из 3 + 1 + 8 + 2 + 4 + 12 + 2 + 2 = 34 байтов (при чем в таком же порядке как в структуре ).

Но реально там:  TLV100000022.  - вообщем всего 14 байтов


Если же я ставлю в объявлении элемент DATE[12]; на первое место вот так (это я делал для эксперимента, хотя для моей задачи это не подходит):

union SENDPRICE
{
    char page[50];
    
    struct 
    { 
          char  DATE[12];
      struct TLVHAD Header;
      WORD Tag;
          WORD Len;
          
    } var; 
}; 

то получаю 444444444447TLV100000022.   - 26 байтов

Как же все таки получить нужную последовательность, объясните мне дуракуsmile?

Автор: N0dwis 30.4.2008, 09:44
Вообще-то то, как располагать структуру в памяти, определяет компилятор, в зависимости от настроек оптимизации (и просто под настроение) он может запросто вставлять пустые места между членами структуры и т.д.
Далее, вот этим "char  DATE[12];" ты объявляешь указатель на строку, который входит в структуру. Никто не обещал, что сама строка будет располагаться в этой же, либо соседней области памяти.

Добавлено через 7 минут и 16 секунд
Судя по названиям, ты все это будешь передавать по сети, могу предложить такой вариант, я так и делал.
Сделай все типы пакетов - классами, и научи их упаковывать все нужные им данные самостоятельно (им то известны все размеры), последовательно их копируя в один буфер. Первые 3 символа - сигнатура пакета. Получатель создает класс такого же типа и уже он распаковывает их.

Автор: maxim1000 30.4.2008, 09:57
Цитата(N0dwis @  30.4.2008,  09:44 Найти цитируемый пост)
Далее, вот этим "char  DATE[12];" ты объявляешь указатель на строку, который входит в структуру. Никто не обещал, что сама строка будет располагаться в этой же, либо соседней области памяти.

нет, char DATE[12] - объявление массива
а уже в выражениях DATE чаще всего конвертироваться в указатель на первый элемент
но эти 12 байт будут точно в структуре и именно после len

Автор: N0dwis 30.4.2008, 10:05
Цитата(maxim1000 @  30.4.2008,  09:57 Найти цитируемый пост)
нет, char DATE[12] - объявление массива
а уже в выражениях DATE чаще всего конвертироваться в указатель на первый элемент
но эти 12 байт будут точно в структуре и именно после len

DATE - фактически и есть указатель на первый элемент, он не конвертируется.
Но то, что 12 байт будут в структуре - ты прав, тут я поторопился... smile 

Автор: DanilSoldatov 30.4.2008, 10:13
Цитата

но эти 12 байт будут точно в структуре и именно после len


как я понимаю они там должны быть, но ведь их нет (имею ввиду в байтовой последовательности)

Цитата

Судя по названиям, ты все это будешь передавать по сети, могу предложить такой вариант, я так и делал.
Сделай все типы пакетов - классами, и научи их упаковывать все нужные им данные самостоятельно (им то известны все размеры), последовательно их копируя в один буфер. Первые 3 символа - сигнатура пакета. Получатель создает класс такого же типа и уже он распаковывает их.


Да, это пакеты для передачи по сети. В Дельфи у меня все работало(там я вместо структур использовал рекорды)
Щас надо на чистый Си (в нем нет классов) все это перевести.
Т.е. мне надо как угодно на выходе получить байты, расположенные в определенном порядке (согласно структуре пакета)
Разве стркутуры это не лучший вариант?

Автор: N0dwis 30.4.2008, 10:56
Только что проверил -  у меня все в page как и должно быть... 
Похоже, это твой компилятор что-то мудрит...

Автор: DanilSoldatov 30.4.2008, 11:22
ДА, все оказывается правильно было

просто я в отладчике смотрел,
а тот показывал page как строку а не как последовательность байтов

и обрывал ее на нулевом байте

Поэтому я посмотрел
page[0], page[1] и т.д. и все ок.

Автор: N0dwis 30.4.2008, 11:32
 smile 

Автор: bel_nikita 30.4.2008, 11:53
Не забываем про http://forum.vingrad.ru/index.php?showtopic=24425&view=findpost&p=168844

Автор: DanilSoldatov 30.4.2008, 14:41
Цитата

Не забываем про выравнивание в структурах

Это как раз кстати. Что-то все предложенные способы вроде испробовал - все равно лишние два байта появляются.

Вот такая последовательность получается из вішеуказанного union SENDPRICE:

84 
76 
86   
17 
-------------TLV17
28 
0 
0 
0 
--------------DWORD len =28
48 
48 
48 
48 
48 
48 
57 
57 
----------------WSCode[8] = 00000099
46 
1 
---------------WORD OperCode=302
0 
0 
-----------------лишние байты
1 
0 
-----------------WORD Tag = 1
14 
0 
------------------WORD len = 14
48 
53 
49 
48 
48 
55 
48 
48 
48 
48 
48 
48 
-----------------DATE[12]= 051007000000


Делал так:

#pragma pack(push, _Struct, 1)
struct TLVHAD
{ 
  TLVHADPrefix Prefix;
  DWORD Len;
  TermID WSCode;
  WORD OperCode;
};
#pragma pack(pop, _Struct)


union SENDPRICE
{
  char page[35];
  
#pragma pack(push, _Struct, 1)    
  struct 
  { 
    struct TLVHAD Header;
    WORD Tag;
    WORD Len;
    MaxDATE DATE;
  } var;  // 34
#pragma pack(pop, _Struct)
};

Автор: MAKCim 30.4.2008, 17:27
DanilSoldatov, 

M
MAKCim
Модератор: Пользуйтесь тегом код!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)