Как я могу получить доступ к членам структуры, если она не выровнена должным образом? - PullRequest
2 голосов
/ 08 января 2011

Боюсь, что я не очень хорош в низком уровне C, я более привык используя объекты в Obj-c, поэтому, пожалуйста, извините, если это очевидный вопрос, или я что-то не так понял ...

Я пытаюсь написать приложение в Cocoa / Obj-C, которое взаимодействует с внешним битом аппаратного обеспечения (до получения наличных.) У меня есть формат данных, которые устройство отправляет и получает - и успешно получил несколько фрагментов данные с устройства.

Например: кассовый аппарат обменивает PLU (ценовые данные) порциями данных в следующем формате: (из документации)

Имя Байт Тип

Name             Bytes    Type

PLU code h        4      long   
PLU code L        4      long
desc              19     char
Group             3      char
Status            5      char 
PLU link code h   4      long 
PLU link code l   4      long
M&M Link          1      char
Min. Stock.       2      int
Price 1           4      long 
Price 2           4      long

Total 54 Bytes

Итак, у меня есть структура в следующей форме для хранения данных из кассы:

typedef struct MFPLUStructure { 
 UInt32   pluCodeH; 
 UInt32   pluCodeL; 
 unsigned char description[19]; 
 unsigned char group[3]; 
 unsigned char status[5]; 
 UInt32   linkCodeH; 
 UInt32   linkCodeL; 
 unsigned char mixMatchLink; 
 UInt16   minStock; 
 UInt32   price[2];  
} MFPLUStructure;  

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

00 00 00 00 4E 61 BC 00 54 65 73 74 20 50 4C 55 00 00 00 00 00 00 00 00 00 00 00 09 08 07 17 13 7C 14 04 00 00 00 00 09 03 00 00 05 BC 01 7B 00 00 00 00 00 00 00

т.е.

  • байты с 46 по 50 равны <7B 00 00 00> == 123, как и следовало ожидать, так как цена установлена ​​на '123' на кассе.

  • байт 43 равен <05> == 5, как и следовало ожидать, так как «связь и совпадение» установлена ​​на 5 на кассе.

  • байты с 39 по 43 равны <09 03 00 00> == 777, как и следовало ожидать, поскольку в коде ссылки установлено значение "777".

  • Байты 27, 28, 29 - это <09 08 07>, представляющие собой три группы (7,8 и 9), которые я ожидаю.

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

Изображение 1 - http://i.stack.imgur.com/nOdER.png

Я предполагаю, что причина этого в том, что пять байтов состояния выталкивают более поздних членов из выравнивания - то есть они выходят за границы машинного слова. Это правильно?

Изображение 2 - i.imgur.com/ZhbXU.png

Прав ли я в этом предположении?
И если да, то как мне правильно вводить и выводить участников?

Спасибо за любую помощь.

Ответы [ 2 ]

3 голосов
/ 08 января 2011

Либо обращайтесь к данным по байтам за раз и собирайте их в более крупные типы, либо memcpy - в выровненную переменную.Последнее лучше, если известно, что данные имеют формат, специфичный для порядка байтов хоста и т. Д. Первое лучше, если данные соответствуют внешней спецификации, которая может не соответствовать хосту.

1 голос
/ 08 января 2011

Если вы уверены, что порядковые номера хоста и провода совпадают, вы также можете использовать упакованную структуру для чтения данных за один проход.Однако это зависит от компилятора и, скорее всего, повлияет на производительность доступа к элементу.

Если предположить gcc , вы будете использовать следующие объявления:

struct __attribute__ ((__packed__)) MFPLUStructure { ... };
typedef struct MFPLUStructure MFPLUStructure;

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

assert(sizeof (MFPLUStructure) == 54);
...