0

I want to typedef a struct in some way if the machine I am on is Little endian and in some other way if it is Big endian.I tried:

unsigned int i = 1; 
   char *c = (char*)&i; 
   if (*c)
   {
       /*Little endian"*/

       typedef struct
    {
    
        unsigned long A : A_BIT_SIZE;
        unsigned long R : R_BIT_SIZE;
        unsigned long E : E_BIT_SIZE;
        unsigned long funct : FUNCT_BIT_SIZE;
        unsigned long opsource : OPSOURCE_BIT_SIZE;
        unsigned long sourcetype : SOURCETYPE_BIT_SIZE;
        unsigned long opdest : OPDEST_BIT_SIZE;
        unsigned long desttype : DESTTYPE_BIT_SIZE;
        unsigned long opcode : OPCODE_BIT_SIZE;

    }command_byte;
   }   
   else
   {
          /*Big endian"*/
                 typedef struct
    {
        unsigned long opcode : OPCODE_BIT_SIZE;
        unsigned long desttype : DESTTYPE_BIT_SIZE;
        unsigned long opdest : OPDEST_BIT_SIZE;
        unsigned long sourcetype : SOURCETYPE_BIT_SIZE;
        unsigned long opsource : OPSOURCE_BIT_SIZE;
        unsigned long funct : FUNCT_BIT_SIZE;
        unsigned long E : E_BIT_SIZE;
        unsigned long R : R_BIT_SIZE;
        unsigned long A : A_BIT_SIZE;
    
    }command_byte;

    }

It compiles, but I am not sure whether this is the valid way to define structs inside an if statement. I am also not sure weather it will work when I actually use the struct. Will at work on header files too? what is the correct way to define a struct if condition is met?

avivgood2
  • 227
  • 3
  • 19
  • Does this answer your question? [C Macro definition to determine big endian or little endian machine?](https://stackoverflow.com/questions/2100331/c-macro-definition-to-determine-big-endian-or-little-endian-machine) – kabanus Jul 05 '20 at 04:53
  • @kabanus I know who to detriment between the different architectures, my problemm is about the definition of structs in if statements – avivgood2 Jul 05 '20 at 04:56
  • @avigood2 `#if IS_BIG_ENDIAN .... #ELSE`? Some of the answers have such constructs. – kabanus Jul 05 '20 at 04:59
  • https://stackoverflow.com/a/9283155/6881240 Has an example. Instead of `#error` define your structures. – kabanus Jul 05 '20 at 05:00
  • @kabanus the code you linked above... does it supports 64 bits mtachin as well? becuse it says 032 – avivgood2 Jul 05 '20 at 05:04
  • My guess is yes, but why don't you just test it? In any case, this is the way to go - Macro if/else. – kabanus Jul 05 '20 at 05:06
  • @kabanus but I don't know the edianess of my matchin. if I would get a false result I wouldent know – avivgood2 Jul 05 '20 at 05:07
  • https://serverfault.com/questions/163487/how-to-tell-if-a-linux-system-is-big-endian-or-little-endian - one google away. – kabanus Jul 05 '20 at 05:08
  • On Linux, one of the answers further down seems easiest - `lscpu | grep Endian`. – kabanus Jul 05 '20 at 05:09
  • 1
    @avivgood2 The endianness of the target machine must be known at *compile* time, so it doesn't make sense to put it inside an `if ... else ...` that is evaluated at runtime. You certainly don't expect the *same* executable to run on *both* little and big endian machines, so by doing it that way you'd always have a block of dead code that's never executed when compiled for a particular target. – dxiv Jul 05 '20 at 06:43

2 Answers2

1

Yes, you can use an if like that. But the typedef command_type can only be used within the innermost containing block that it was defined in.

Therefore there is no advantage over defining typedef ... command_type_big_endian and typedef ... command_type_little_endian, you cannot share the code either way.

You could use preprocessor macros to aid in avoiding repetition; then you could write the bulk of a serialization and deserialization macro only once and instantiate that for each command_type variation.

1

You can define them both, and put them in an union:


#include <stdio.h>

#define A_BIT_SIZE 3
#define R_BIT_SIZE 3
#define E_BIT_SIZE 2
#define FUNCT_BIT_SIZE 8
#define OPSOURCE_BIT_SIZE 2
#define SOURCETYPE_BIT_SIZE 2
#define OPDEST_BIT_SIZE 2
#define DESTTYPE_BIT_SIZE 2
#define OPCODE_BIT_SIZE 8

typedef union {
        struct { /*Little endian"*/
        unsigned A : A_BIT_SIZE;
        unsigned R : R_BIT_SIZE;
        unsigned E : E_BIT_SIZE;
        unsigned funct : FUNCT_BIT_SIZE;
        unsigned opsource : OPSOURCE_BIT_SIZE;
        unsigned sourcetype : SOURCETYPE_BIT_SIZE;
        unsigned opdest : OPDEST_BIT_SIZE;
        unsigned desttype : DESTTYPE_BIT_SIZE;
        unsigned opcode : OPCODE_BIT_SIZE;
        } le;
        struct { /*Big endian"*/
        unsigned opcode : OPCODE_BIT_SIZE;
        unsigned desttype : DESTTYPE_BIT_SIZE;
        unsigned opdest : OPDEST_BIT_SIZE;
        unsigned sourcetype : SOURCETYPE_BIT_SIZE;
        unsigned opsource : OPSOURCE_BIT_SIZE;
        unsigned funct : FUNCT_BIT_SIZE;
        unsigned E : E_BIT_SIZE;
        unsigned R : R_BIT_SIZE;
        unsigned A : A_BIT_SIZE;
        } be;
    } command_byte;

int main(void)
{
command_byte stuff={{0,}};

stuff.le.opcode = 0x7f;
printf("Le = %x\n", (unsigned) stuff.le.opcode);
printf("Be = %x\n", (unsigned) stuff.be.opcode);

return 0;
}
wildplasser
  • 43,142
  • 8
  • 66
  • 109