Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

152
Visualizações
Union fails to decode byte array

The following code fails to decode the latitude and longitude. The output is: 132, 1, 1645780273, 77276230, 0, -0.000000, 0.000000, doing a wrong conversion on the last 2 values latitude & longitude. If I remove the first 4 values and delete uint32_t identifiers; from the struct i get the correct result 132, 1, 1645780273, 77276230, 0, 59.877871, 10.465200

Any help in understanding this behavior ist very appreciated.

#include <stdio.h>
#include <string.h>
int main() {
    union  {
        unsigned char bytes[36];
        struct{
            uint32_t identifier;
            uint16_t telegram_size;
            uint16_t telegram_version;
            uint32_t seconds;
            uint32_t nanoseconds;
            uint32_t stat;
            double latitude;
            double longitude;
      }unpack;
    }telegram;

    unsigned char values[] = {0x23, 0x4B, 0x4D, 0x42, 0x84, 0x00, 0x01, 0x00, 0x31, 0x9d, 0x18, 0x62, 0x46, 0x24, 0x9b, 0x04, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x3e, 0x2c, 0x11, 0x5e, 0xf0, 0x4d, 0x40, 0xCA, 0x32, 0xC4, 0xB1, 0x2E, 0xEE, 0x24, 0x40};
    memcpy(telegram.bytes, values, 36);

    for (int i=0;i<36;i++){
        printf("%02X ", telegram.bytes[i]);
    }
    printf("\n%u, %u, %u, %u, %u, %f, %f\n", telegram.unpack.telegram_size, telegram.unpack.telegram_version, telegram.unpack.seconds, telegram.unpack.nanoseconds, telegram.unpack.stat, telegram.unpack.latitude, telegram.unpack.longitude);
    return 0;
}

Update: As far as I understood from the comments below the struct looks like this: enter image description here

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

This has to do with struct padding.

Generally speaking, members of a struct start at an offset which is a multiple of that member's size for alignment purposes. Because of this, there are 4 padding bytes between the stat and latitude members so that the latter can reside at an offset that is a multiple of 8. That means the struct is 4 bytes larger than you think it is.

If you're able to, you should rearrange the members so that they align at a natural offset so that there is no padding between the members (although there may still be padding at the end).

If that's not an option, you can pack the struct using a compiler-specific attribute. If you're using gcc, you would do the following:

    struct __attribute__((__packed__)) {
        uint32_t identifier;
        uint16_t telegram_size;
        uint16_t telegram_version;
        uint32_t seconds;
        uint32_t nanoseconds;
        uint32_t stat;
        double latitude;
        double longitude;
  }unpack;

Note also that on some architectures, an unaligned read or write can cause a crash.

over 4 years ago · Santiago Trujillo Relatório

0

You are assuming that the structure is laid out with all members contiguous. That is not a safe assumption. Implementations are free to insert arbitrary padding into structure layouts between members and after the last member. In practice, they will do so in a manner that allows them to ensure that all members can be properly aligned in memory.

In your particular case, your 8-byte doubles want to be aligned on 8-byte boundaries. Your implementation is ensuring that they can be by putting them at offsets from the beginning of the structure that are multiples of 8 bytes. That involves inserting four bytes of otherwise unused padding between stat and latitude, which your initialization does not account for. The overall structure will also have an 8-byte alignment requirement, and its total size will be a multiple of 8 bytes.

Removing the four-byte initial member allows the two doubles to be aligned without any padding, which is why that variation on your program worked as you expected.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda