Bepaal de bytevolgorde van uint32_t

Ik converteer een vxWorks-applicatie naar Linux.

Eerder had ik een unie met een woord en een struct zodat wanneer ik toegang kreeg tot de leden van de struct , Ik zou de layout van het woord kunnen gebruiken om mijn leden struct te bouwen.

Ik weet echter niet meer hoe ik dit heb bedacht en het werkt op de vxWorks-box. Op mijn vxWorks-instantie is de lay-out:

typedef union Status
{
    struct fields
    {
        uint32_t byteA : 1;//<31>
        uint32_t blank : 23;//<30:8>
        uint32_t bytesN : 8;//<7:0>
    } fields;

    uint32_t word;
}

Ik ben al wat endeense problemen tegengekomen tijdens het porten van vxWorks naar Linux. Dus het uitzoeken van de layout van uint32_t op Linux is belangrijk.

0
Wat is de vraag?
toegevoegd de auteur anatolyg, de bron
zou zoiets als dit niet moeten werken? uint32_t foobar = 0x00ff00ff; if (((char *) foobar) [0] == 0xff)/* one endianess */else/* the other */
toegevoegd de auteur Alex, de bron
toegevoegd de auteur Gnawme, de bron

2 antwoord

U kunt zien door een aanwijzer naar een int te verplaatsen die de waarde 0x01 bevat en deze naar een teken * te casten. Als de eerste waarde gelijk is aan nul, dan is het systeem big endian, anders is het klein endian.

Hier is een voorbeeld:

#include 
#include 

int main(void)
{
   uint32_t   val  = 0x01;
   char     * buff = (char *)&val;

   if (buff[0] == 0)
   {
      printf("Big endian\n");
   } else {
      printf("Little endian\n");
   };

   return(0);
}

Ik heb deze methode gebruikt voor Linux, Solaris, OS X en FreeBSD.

3
toegevoegd
@ 0A0D Dus wil je dit doen? Status x; x.word = 40; printf ("% d", x.fields.bytesN);
toegevoegd de auteur anatolyg, de bron
Uw probleem is dat u niet de volgorde omkeert waarin u de bytes opent bij toegang tot Status.word . Op Big Endian (hardware wordt een geheel getal opgeslagen als B3, B2, B1, B0 echter op een Little Endian wordt een geheel getal opgeslagen als B0, B1, B2, B3. Dit betekent dat op op grote endian hardware ((Status. fields.byteN == 15) && (Status.word == 0x0F)) terwijl op kleine endian hardware ((Status .fields.byteN == 15) && (Status.word == 0x0F000000)) Wanneer u overschakelt van een groot endian platform, moet u ofwel de bitvolgorde van Status.fields omkeren of de bitvolgorde om toegang te krijgen tot Status.word omkeren.
toegevoegd de auteur David M. Syzdek, de bron
@anatolyg je moet je vraag verfijnen Wat wil je doen als je de bytevolgorde niet te weten komt?
toegevoegd de auteur Alex, de bron
Ja, ik weet hoe ik dit moet doen. Maar als woord het nummer 40 bevat, wil ik dat getal in bytesN, niet in blanco of bytesA. Dat is de reden waarom de lay-out belangrijk is. Hoe uint32_t specifiek is opgemaakt.
toegevoegd de auteur user195488, de bron

Van je reactie tot de andere antwoord , je wilt wat er ook is ingepakt in het woord lid van de vakbond om te verschijnen in het lid fields.bytesN . Om dit te bereiken, moet u ofwel een soort van pre-build-proces hebben dat de veld bitvelden op de juiste manier plaatst na het detecteren van machine-endianness, of 2 structuren creëren, één voor grote endian en de andere voor little endian.

typedef union Status
{
    struct fieldsBE
    {
        uint32_t byteA : 1;//<31>
        uint32_t blank : 23;//<30:8>
        uint32_t bytesN : 8;//<7:0>
    } fieldsBE;

    struct fieldsLE
    {
        uint32_t bytesN : 8;//<7:0>
        uint32_t blank : 23;//<30:8>
        uint32_t byteA : 1;//<31>
    } fieldsLE;

    uint32_t word;
};

int main()
{
  bool isBigEndian = DetectEndianness();//returns true if big endian

  Status status;

  status.word = 40;

  if( isBigEndian ) {
    uint8_t bytesN = status.fieldsBE.bytesN;

  } else {
    uint8_t bytesN = status.fieldsLE.bytesN;

  }
}

Als u slechts weinig endian in uw poort wilt ondersteunen, gebruikt u natuurlijk de lay-out van fieldsLE in plaats van de originele lay-out die u heeft getoond.

1
toegevoegd
het omkeren van de bestelling werkte.
toegevoegd de auteur user195488, de bron
maar ik moest bytesN wijzigen in 31, blanco in 23, en byte in 1.
toegevoegd de auteur user195488, de bron