Форум программистов, компьютерный форум, киберфорум
netBool
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Преобразование структуры в массив байт

Запись от netBool размещена 06.04.2018 в 16:38
Показов 6834 Комментарии 9

Уже полтора дня потерял в поисках ответа, почему не работает вот этот код:
C++
1
2
3
      BYTE arr[6];
      BYTE* _arr = arr;
      *((jmp_far*)_arr) = jump;
где jump - это jmp_far, а BYTE - unsigned char

C++
1
2
3
4
5
6
struct jmp_far
{
  BYTE instr_push;  //здесь будет код инструкции push
  DWORD arg;         //аргумент push
  BYTE  instr_ret;    //здесь будет код инструкции ret
};
Изначально jump заполнен данными, которые хорошо видны в отладчике, но после присвоения указателя разыменнованному указателю на массив байт, все рушится. Фактически передается только 1й байт (среда VS2010)

Оказывается, есть такая маленькая настроечка:
Проект->Свойства->Свойства конфигурации->C++->Создание кода->Выравнивание членов структур->1 байт (\Zp1).
И все, вуаля! Все заработало!!
но блин, ребята, полтора дня!

До этого стояло "по умолчанию"... так вот по умолчанию, видимо, 4 байта...

PS: как верно подметил в комментариях Rius, что можно было это сделать и с помощью #pragma (работает для MinGW и GCC). Под QTCreator (где нет настроек с \Zp1) я сделал так:
C++
1
2
3
4
5
6
#pragma pack(1)
struct jmp_far
{
     //поля
};
#pragma pack()
PPS: На linux.org встретил мнение, что выравнивание по 1 байту увеличивает время доступа к полям структуры. Не проверял, в моем случае скорость не имела сильного значения.

Но можно, конечно, и без выравнивания сделать.
Думаю, на нашем примере будет наиболее оптимально так:
C++
1
2
3
4
    BYTE ch[6];
    *ch = jump.instr_push;        
    *(DWORD*)(ch+1) = jump.arg;
    *(ch+5)=jump.instr_ret;
Размещено в C++
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 9
Комментарии
  1. Старый комментарий
    Аватар для Rius
    но блин, ребята, полтора дня!
    Лучше 5 часов потратить, потом за 5 минут долететь!
    Там ещё есть директивы, влияющие на конкретную указанную структуру, а не на весь проект.
    Вроде так выглядит:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    #pragma pack(push)  /* сохранить текущие настройки выравнивания (или упаковки?) */
    #pragma pack(1)     /* установить выравнивание в 1 байт */
     
    struct jmp_far
    {
      BYTE instr_push;  //здесь будет код инструкции push
      DWORD arg;         //аргумент push
      BYTE  instr_ret;    //здесь будет код инструкции ret
    };
     
    #pragma pack(pop)   /* вернуть предыдущие настройки */
    Настройки проекта вы можете легко забыть и потерять, если скопируете код в другой проект.
    А вот в коде директивы останутся.
    Запись от Rius размещена 06.04.2018 в 17:47 Rius вне форума
  2. Старый комментарий
    Аватар для Avazart
    Ну или можно упаковывать структуру в байты отдельной ф-цией так как это Вам надо (почленно)
    и распаковывать так же.
    Запись от Avazart размещена 06.04.2018 в 17:53 Avazart вне форума
  3. Старый комментарий
    Аватар для netBool
    Цитата Сообщение от Rius
    Лучше 5 часов потратить, потом за 5 минут долететь!
    Там ещё есть директивы, влияющие на конкретную указанную структуру, а не на весь проект.
    Вроде так выглядит:
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    #pragma pack(push)  /* сохранить текущие настройки выравнивания (или упаковки?) */
    #pragma pack(1)     /* установить выравнивание в 1 байт */
     
    struct jmp_far
    {
      BYTE instr_push;  //здесь будет код инструкции push
      DWORD arg;         //аргумент push
      BYTE  instr_ret;    //здесь будет код инструкции ret
    };
     
    #pragma pack(pop)   /* вернуть предыдущие настройки */
    Настройки проекта вы можете легко забыть и потерять, если скопируете код в другой проект.
    А вот в коде директивы останутся.
    Как раз хотел добавить, что в QTCreator под MinGW не нашел таких настроек и вышел из ситуации с помощью pragm, но вы меня опередили))
    Запись от netBool размещена 07.04.2018 в 11:28 netBool вне форума
  4. Старый комментарий
    Аватар для _SayHello
    В GCC можно объявлять структуру с атрибутом
    C
    1
    
    __attribute__((packed))
    эффект такой же вроде
    Запись от _SayHello размещена 23.04.2018 в 12:34 _SayHello вне форума
  5. Старый комментарий
    Аватар для netBool
    Кстати, если нужно копировать структуру в середину массива, то можно воспользоваться конструкцией:
    C++
    1
    2
    3
    
        BYTE* bytes = new BYTE[14];
        bytes = old;
        *((jmp_far*)(bytes+7)) = jmpToOrigin;
    где jmp_far - тип объекта jmpToOrigin
    Запись от netBool размещена 04.05.2018 в 09:59 netBool вне форума
  6. Старый комментарий
    Аватар для netBool

    Не по теме:


    Нашел еще на стеке, а потом и тут наткнулся на решение для GCC/MinGW в виде ключа компиляции -mno-ms-bitfields
    Вроде тоже на упаковку влияет. Пока не проверял

    C++ (Qt)
    1
    
    QMAKE_CXXFLAGS += -mno-ms-bitfields

    Запись от netBool размещена 11.06.2018 в 12:00 netBool вне форума
  7. Старый комментарий
    Аватар для Rius
    Кстати, если нужно копировать структуру в середину массива, то можно воспользоваться конструкцией:
    Я так на ARM7TDMI сделал как-то раз. Всё же здесь просто и очевидно. А потом искал причину бага на ровном месте: число в один массив нормально копируется, а в другой такой же - хрень получается.
    Оказалось, требовалось выравнивание по границе 4 байт (32-битное слово).

    Так что вы поосторожнее с таким.

    О выравнивании памяти на ARM процессорах на простом примере.
    Запись от Rius размещена 11.06.2018 в 12:11 Rius вне форума
  8. Старый комментарий
    Аватар для netBool
    Оказалось, требовалось выравнивание по границе 4 байт (32-битное слово).
    Любопытно. Спасибо

    Видимо, это особенность самого Си-компилятора под ARM, а не процессора ARM. Ведь memcpy сработало
    Запись от netBool размещена 11.06.2018 в 12:51 netBool вне форума
  9. Старый комментарий
    Аватар для Rius
    Сработало, да. Но причина и аппаратная в том числе.
    The curious case of unaligned access on ARM
    Запись от Rius размещена 11.06.2018 в 16:47 Rius вне форума
 
Новые блоги и статьи
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru