Converting bytes array to integer

前端 未结 2 1838
既然无缘
既然无缘 2020-12-21 16:38

I have a 4-byte array (data) of type uint8_t, which represents a speed data integer. I\'m trying to cast this array to uint32_t integer (speed), m

相关标签:
2条回答
  • 2020-12-21 17:16

    Your code doesn't work because during data=(uint8_t*)speed; you don't get a "lvalue" for data, you just get an array type which can't be used in assignment or any form of arithmetic. Similarly, speed=( uint32_t)*data; is a bug because that only gives you the first item in the array.

    The only correct way you should do this:

    volatile uint8_t data[4] = {0x00 , 0x00, 0x00, 0x00};
    volatile uint32_t speed;
    
    speed = (uint32_t)data[0] << 24 |
            (uint32_t)data[1] << 16 |
            (uint32_t)data[2] <<  8 |
            (uint32_t)data[3] <<  0;
    
    speed=speed*10;
    
    data[0] = (uint8_t) ((speed >> 24) & 0xFFu);
    data[1] = (uint8_t) ((speed >> 16) & 0xFFu);
    data[2] = (uint8_t) ((speed >>  8) & 0xFFu);
    data[3] = (uint8_t) ((speed >>  0) & 0xFFu);
    

    This is 100% portable and well-defined code. No implicit promotions take place. This code does not rely on endianess or other implementation-defined behavior. Why write code that does, when you can write code that doesn't?

    0 讨论(0)
  • 2020-12-21 17:41

    To be safe according endianess, portable and secure, you should recreate your data:

    speed = ((uint32_t)data[0]) << 24 
          | ((uint32_t)data[1]) << 16 
          | ((uint32_t)data[2]) << 8 
          | ((uint32_t)data[3]);
    

    or

    speed = ((uint32_t)data[3]) << 24 
          | ((uint32_t)data[2]) << 16 
          | ((uint32_t)data[1]) << 8 
          | ((uint32_t)data[0]);
    

    Choose solution according position of most significant byte


    You get an "assignment to expression with array type" error because you can't assign directly an array: data=(uint8_t*)speed; is totally forbidden in C, you definitively can't have an array for lvalue. You have to do inverse operation:

    data[0] = (uint8_t)((speed >> 24) & 0x00FF);
    data[1] = (uint8_t)((speed >> 16) & 0x00FF);
    data[2] = (uint8_t)((speed >> 8) & 0x00FF);
    data[3] = (uint8_t)(speed & 0x00FF);
    

    or, according position of most significant byte:

    data[3] = (uint8_t)((speed >> 24) & 0x00FF);
    data[2] = (uint8_t)((speed >> 16) & 0x00FF);
    data[1] = (uint8_t)((speed >> 8) & 0x00FF);
    data[0] = (uint8_t)(speed & 0x00FF);
    

    EDIT

    Don't use cast or memcpy as mention in commentaries and original answer: in addition of non portability issues, you will have security issues, according alignment restrictions and aliasing rules on some platform, compiler can generate incorrect code - thanks to user694733 | see here - thanks to Lundin

        speed = *((uint32_t *)data); // DANGEROUS NEVER USE IT
        *((uint32_t *)data) = speed; // DANGEROUS NEVER USE IT
    
    0 讨论(0)
提交回复
热议问题