Перевод целого в байты и обратно

Тема в разделе "Arduino & Shields", создана пользователем Михаил123, 3 сен 2020.

  1. akl

    akl Гуру

    блин серьезно, кто-нибудь может объяснить, почему вот это работает?


    Код (C++):
    void longtoarr(uint32_t nom, uint8_t* arr){
        union un{uint32_t n; uint8_t arr_[4];}u;
        u.n=nom;
        for(int i=0; i<4; i++){arr[i]=u.arr_[i];}
    }
    uint32_t arrtolong(uint8_t* arr){
        uint8_t arr_[4];
        //for(int i=0; i<4; i++){arr_[i]=arr[i];}
        uint32_t &n = (uint32_t&)arr_;
        return n;
    }

    int main()
    {
        unsigned char barray[4];
        uint32_t a = 0x2134ff56;
        uint32_t b = 0;
        printf("%X\n",a);
        longtoarr(a, barray);
        b = arrtolong(barray);
        printf("%X\n",b);
    }
    каким образом arrtolong возвращает нужную цифру, ведь ее нету в массиве arr_?



    кстати а в ардуино не пожрет ли это memcpy много памяти? как некоторые другие стандартные функции вроде strcpy
     
  2. b707

    b707 Гуру

    не пожрет, memcpy в куче мест в ардуино уже используется и так, поэтому место будет израсходовано только на вызов функции
     
  3. b707

    b707 Гуру

    не знаю, с такими вопросами к котику ( Asper_Daffy :)
    Зачем это все, когда эта жуть в коде заменяется двумя строчками?
     
  4. akl

    akl Гуру

    чтоб не быть голословным
    [​IMG]

    наверно это какой-то баг и глюк
     
    Михаил123 нравится это.
  5. b707

    b707 Гуру

    а в таком коде какой ответ будет?
    Код (C++):
    void longtoarr(uint32_t nom, uint8_t* arr){
        union un{uint32_t n; uint8_t arr_[4];}u;
        u.n=nom;
        for(int i=0; i<4; i++){arr[i]=u.arr_[i];}
    }
    uint32_t arrtolong(uint8_t* arr){
        uint8_t arr_[4];
        //for(int i=0; i<4; i++){arr_[i]=arr[i];}
        uint32_t &n = (uint32_t&)arr_;
        return n;
    }

    int main()
    {
        unsigned char barray[4];
        uint32_t bb = 0x11223344;
        uint32_t a = 0x2134ff56;
        uint32_t aa = 0xccddeeff;
        uint32_t b = 0;
        printf("%X\n",a);
        longtoarr(a, barray);
        b = arrtolong(barray);
        printf("%X\n",b);
        printf("aa = %X\n",aa);
        printf("bb = %X\n",bb);
    }
     
    Последнее редактирование: 4 сен 2020
    akl нравится это.
  6. Asper Daffy

    Asper Daffy Иксперд

    Не должно и не работает. Если кажется, что работает, значит просто случайно массив arr_ лёг на то место памяти, где раньше было нужное число. Сломается от любого чиха в программе.
     
    Andrey12, akl и b707 нравится это.
  7. у меня отлично работает. как до такого додумался?
     
  8. akl

    akl Гуру

    строчку с копированием массива не забыл раскомментировать?
    но лучше использовать вот такие функции с memcpy, оно как казалось даже немного памяти экономит
    Код (C++):

    void longtoarr(uint32_t *nom, uint8_t* arr){
        memcpy(arr,(uint8_t*)nom,4);
    }
    void arrtolong(uint8_t* arr, uint32_t *nom){
        memcpy((uint8_t*)nom,arr,4);
    }
    int main()
    {
        unsigned char barray[4];
        uint32_t a = 0x12345678;
        uint32_t b = 0;
        uint32_t c = 0;
        printf("%X\n",a);
        longtoarr(&a, barray);
        arrtolong(barray,&b);
        printf("%X\n",b);
        arrtolong(barray,&c);
        printf("%X\n",c);
    }
     
  9. asam

    asam Гик

    Можно и без memcpy
    Код (C++):
    void longtoarr(uint32_t *nom, uint8_t* arr)
    {
      uint32_t *a = (uint32_t*) arr;
      *a = *nom;
    }
    void arrtolong(uint8_t* arr, uint32_t *nom){

      uint32_t *a = (uint32_t*) arr;
      *nom = *a;
    }
     
    Михаил123 и akl нравится это.
  10. akl

    akl Гуру

    о я как раз так хотел чтобы вот так хитро было. Но ниче не получалось. а вот это работает
     
  11. не забыл расскоментировать. иначе как бы работало?
     
  12. прикольно. обмен ссылками
     
  13. Asper Daffy

    Asper Daffy Иксперд

    Где там ссылки? Ни одной, вроде, нету.
     
    Limoney нравится это.
  14. как распознать отрицательное значение?
     
  15. прикольно, но не пошло
     
  16. Igor68

    Igor68 Гуру

    По моему проще так:
    Код (C++):

    uint32_t w = (*(uint32_t*)(&DataSl[0]));
     
    Это для безнакового типа, а это:
    Код (C++):

    int32_t w = (*(int32_t*)(&DataSl[0]));
     
    для знакового

    Ну и обратно:
    Код (C++):

    (*(uint32_t*)(&DataSl[0])) = w; //где-то сказано uint32_t w
     
    Это для безнакового типа, а это:
    Код (C++):

    (*(int32_t*)(&DataSl[0])) = w; //где-то сказано int32_t w
     
    для знакового

    Только не забываем как и везде про "выравнивание" - не редко важно(разрядность системы 16, 32 и выше бит).
     
    Последнее редактирование: 20 сен 2020
  17. спасибо
    я не понял про "выравнивание"
     
  18. Igor68

    Igor68 Гуру

    Если у Вас 32-битная система (ARM и др) если нахождение младшего байта массива находится по адресу не кратному адресации к примеру будет бардак. Для 16-битных это просто нечётный адрес младшего байта будет бардак. В 8-битных системах значения не имеет - там всё кратно байту. Как правило эта задача отводится компилятору, ну и организация в структурах (объявленных).
    Впервые я с этим столкнулся когда организовывал связь сервера и клиента у каждого из которых была своя архитектура. При этом идентичные программы компилировались для каждой архитектуры своим компилятором. При обмене было несоответствие размеров пакетов по socket и соответственно их содержимого. Это как пример.
     
    Последнее редактирование: 20 сен 2020
    SergeiL нравится это.
  19. при положительных значениях всё нормально работает, а вот при отрицательных, например, -1, приходит из Nextion
    246,255,255,255
    и тут - беда
     
  20. Igor68

    Igor68 Гуру

    Бред какой -то. Используйте int32_t а не uint32_t вот и всё. Там как раз старший бит числа это знак.
     
    Последнее редактирование: 20 сен 2020