Сегодня 256-ой день года. С днём программиста!

Тема в разделе "Флудилка", создана пользователем AlexU, 13 сен 2018.

  1. DIYMan

    DIYMan Guest

    Mitrandir нравится это.
  2. AlexU

    AlexU Гуру

    Почти... Это синтаксис какого языка программирования?
     
  3. parovoZZ

    parovoZZ Гуру

    А вот, кстати, вопрос.
    Если в массив из байт вставить integer, то компилятор сместит адрес следующего элемента.
    А если взять массив из integer и в один из элементов таким же макаром вставить байт. Сместит ли компилятор адрес следующего элемента?
     
  4. Igor68

    Igor68 Гуру

    Это просто соответствие...
     
  5. Igor68

    Igor68 Гуру

    Например?
     
  6. parovoZZ

    parovoZZ Гуру

    а я в минус ушел.
     
  7. Igor68

    Igor68 Гуру

    Вопрос на встречу... вот:
    Код (C++):
    typedef struct _test
    {
       char        valch;
       uint8_t    valu8;
       char        valch2;
       int16_t    val16;
       float        valf;
       uint8_t    valu82;
       uint32_t  val32;
    } test;
    Каким образом компилятор сделает выравнивание... и как надо расположить элементы в структуре, что бы обойтись без #pragma? И одинаково ли разные компиляторы делают выравнивание? И что надо сделать, что бы независимо от разных компиляторов данные для них были идентичны?
     
  8. DIYMan

    DIYMan Guest

    Нет, емнип, по стандарту - это отдано на откуп компилятору.
    Очевидно, #pragma pack
    Зависит от компилятора.
     
  9. Igor68

    Igor68 Гуру

    Это точно, но как сделать если по локальной сети передаётся пакет... с этой структурой. И одна машина(x32) с рабочим кодом кодом на VisualStudio, другая(x64) тоже на VisualStudio, третья(x32) GCC Debian, четвёртая(x64) GCC Debian, пятая(Moxa ARM9) GCC Linux, шестая(ARM9) WindowsMobile на VisualStudio2005, седьмая Raspberry PI(32 бита) GCC, восьмая(Raspberry PI 3 64 бита) GCC... и так далее.
    И все данные должны быть идентичны... по выравниванию и соответственно идентичны. Вот в этом и вопрос. Для локальной машины значения не имеет... и #pragma pack на них работает по разному - уже испытано.
     
  10. DIYMan

    DIYMan Guest

    Для этого существуют протоколы, где обговорено всё, вплоть до порядка байт. Очевидно же :)
     
    Mitrandir нравится это.
  11. DIYMan

    DIYMan Guest

    Что, #pragma pack(push,1) работает по разному? Не верю. Другое дело, что порядок байт - бывает разный, но если тулчейн поддерживает #pragma pack, то по команде #pragma pack(push,1) он просто обязан выровнять все данные по границе 1 байт. Там есть нюансы с битовыми полями, емнип, в остальном - всё выравнивается по 1 байту.
     
  12. SergeiL

    SergeiL Оракул Модератор

    Так вроде #pragma pack для этого и придумана, позволяет убрать выравнивание.
    Плюс - uint8_t, uint16_t , а не int, unsigned и word, длина которых может отличаться в разных средах.
     
  13. DIYMan

    DIYMan Guest

    Уточнение: не убрать выравнивание, а - выровнять по указанной границе. Плюс - есть нюанс с битовыми полями, например (на память пишу):

    Код (C++):

    #pragma pack(push,1)

    typedef struct
    {
      uint16_t b16_1;
      uint16_t b16_2;
      uint8_t b8;
    } STRUCT_1;

    #pragma pack(pop)

    #pragma pack(push,1)

    typedef struct
    {
      uint16_t bitfield1 : 3;
      uint16_t bitfield2 : 4;
      uint8_t b8;
    } STRUCT_2;

    #pragma pack(pop)

    void setup()
    {
      Serial.begin(57600);
      Serial.println(sizeof(STRUCT_1));
      Serial.println(sizeof(STRUCT_2));

    }

    void loop() {}
     
    В первом случае - размер 5, во втором - 2. Хотя переменные битовых полей объявлены как uint16_t и, по формальной логике - компилятор должен бы оставлять неиспользуемые биты, в нашем случае второй структуры - это второй её байт.

    Вот не буду врать - это зависит от специфики компилятора или что-то в стандарте про выравнивание битовых полей прописано. Просто помню, что с битовыми полями - есть нюанс (с). Похоже, таки специфика компилятора.
     
  14. SergeiL

    SergeiL Оракул Модератор

    Имел в виду включить выравниивание до байта :)
    С битовыми полями в структурах практики работы не было.

    UPD: Сейчас посмотрел в help, не было в том MS Си Push и Pop в #pragma pack :)
    Код (C++):
    #pragma pack(1)

    typedef struct {
      uchar  CRC_Flag;  // Флаг изменения CRC
      unsigned  State;  // Состояние
      uchar  Link_Up_Flag;  // Флаг установления связи

      uchar  Recive_Channel;  // Номер командного канала

      void (_interrupt _far *Event_Handler)( void ); // Обработчик событий

      unsigned  Com_Descriptor;  // Дискрипрор драйвера RS-232
      unsigned  Com_Descriptor_Inp_IExch;  // Дискрипрор приемн. обменника
      unsigned  Com_Descriptor_Out_IExch;  // Дискрипрор перед.  обменника

      unsigned  In_Chn_IExc;  // Обменник по записи
      unsigned  Out_Chn_IExc;  // Обменник по чтению


      char far  *Chn_I_Buf_Seg;  // Адpес начала буфеpа
      char far  *Chn_I_Buf_Tail;  // Указатель хвоста буфеpа

      char far  *Chn_O_Buf_Seg;  // Сегментный адpес начала буфеpа
      char far  *Chn_O_Buf_Tail;  // Указатель хвоста буфеpа

      unsigned  Timer;
      unsigned  Telem_Timer;
      unsigned  Input_Counter;

      unsigned  STX_flag;
      unsigned  ETX_flag;

      unsigned  Output_Answer_Flag;
      unsigned  Output_Wait_Flag;
      unsigned  Break_TO_Flag;
      uchar  Old_Event_State;

      uchar  ErrCounter;
      uchar  ErrDataCounter;
      uchar  ErrGLCounter;

    } PR_CHN_DESC_STRUCT;

    #pragma pack()
     
     
    Последнее редактирование: 13 сен 2018
  15. Igor68

    Igor68 Гуру

    Я делал на убывание... и везде прокатывало. Испытано на обмене по сетевому соединению на разного типа машинах:
    Код (C++):
    typedef struct _test
    {
       //сначала самые тяжелые
       uint32_t    val32; //4 байта
       float          valf;   //то же 4 байта
       uint32_t    buf32[24];
       float         buff[16;  
       ...
       //потом полегче
       uint16_t     valu16;
       int16_t      vali16;
       uint16_t    bufu16[32];
       int16_t     bufi16[20];
       ...
       //потом ещё легче
       uint8_t     valu8;
       int8_t      vali8;
       uint8_t     bufu8[200];
       int8_t      bufi8[10];
       ....
    }  test;
    И компилятор не надо тыкать носом... и нет пустых мест.
     
  16. SergeiL

    SergeiL Оракул Модератор

    А я бы поставил:
    Код (C++):
    #pragma pack(1)
    .....
    #pragma pack()
    Хуже от этого не будет,
    но есть уверенность, что компилятор не будет заниматься выравниванием по своим критериям.
     
    Последнее редактирование: 13 сен 2018
  17. SergeiL

    SergeiL Оракул Модератор

    Пока залезал сегодня в свои старые исходники, вспомнились еще такие варианты #pragma:
    Код (C++):
    #pragma check_stack( off )
    #pragma check_pointer( off )
    #pragma intrinsic( _enable, _disable )
    Кто расскажет для чего, и зачем их нужно использовать? ;)
     
    Последнее редактирование: 13 сен 2018
  18. Igor68

    Igor68 Гуру

    Попробуйте на разных компиляторах в разных средах разработки и стразу сами закричите: ХУЖЕ БУУУУДЕТ! Если бы сам не испытал... не говорил бы. Важна ещё и последовательность данных!!!
    На одном конце:
    Код (C++):
    struct TTT
    {
    uint8_t   a;
    uint16_t b;
    };

    struct TTT ttt;


    //а потом:
    ttt.a = 3;
    ttt.b =254;

    //и передаём
    send(&ttt, sizeof(TTT));

    //и на приёме другого устройства с другой платформой

    struct TTT ttt;
    recv(&ttt, sizeof(TTT));

    //
    printf("a=%i\n",ttt.a);
    printf("b=%\n",ttt.b);

     
    Да хоть 100 раз #pagma pack поставьте... не скажу про GCC, а вот к примеру от microsoft... так Вы к ним и обратитесь с вопросом:
    - А почему у вАС всё через жопу?
     
  19. SergeiL

    SergeiL Оракул Модератор

    Так а что sizeof() возвращает?, я ему доверяю ;)
     
  20. parovoZZ

    parovoZZ Гуру

    А как выравнивание происходит? В недостающие биты записываются нули?