Thread: Backwards uint16_t?

  1. #1
    Registered User
    Join Date
    Feb 2008
    Posts
    58

    Smile Backwards uint16_t?

    Hello

    I have a function that takes a strut and turns it into a uint8_t array. This code is running on an embedded device and works well. I have recently copied this code to a linux development environment to try to get it to work there as well.

    Everything works as it should, however the 16bit variables in my struct are produced backwards:

    Code:
    typedef struct {
    	
    	uint8_t deviceType;
    	uint8_t RSSI;
    	uint16_t batteryVoltage;
            uint16_t errors;
    
    } AppAuxSLANPacket_t;
    So when I want to convert my struct into a byte array (buffer) I do this:

    Code:
     {
    
    transcribePacket((uint8_t*)&AuxSLANPacket, 6);
    
    }...
    
    void transcribePacket(uint8_t message[], uint8_t length) {
    	
    	int x, y = 0;
    	
    	for (x = 0; x < length; x++) {	
    		buffer[x] = message[x];
    	} // for
    
    } // transcribe
    This works fine on the embedded device and I get a byte array with all of the data of the structs in it. If I do the same in the linux dev environment the 16bit variables are written to the byte array backwards:

    embedded device example byte array: (correct)

    0x10 | 0x20 | 0x01 | 0xFF | 0xDA | 0x33

    Linux dev environment example for same data:

    0x10 | 0x20 | 0xFF | 0x01 | 0x33 | 0xDA

    Here the 16 bit values have been entered into the byte array, but put in backwards.

    It is exactly the same code doing this on each platform which leads me to think there is a compiler options somewhere I need to change.

    Has anyone got any ideas?

    may thanks indeed

    David

  2. #2

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > It is exactly the same code doing this on each platform which leads me to think there is a compiler options somewhere I need to change.
    No, there's something in your code which needs to change.

    Endianness - Wikipedia, the free encyclopedia

    There is no compiler flag which can magic away endian problems for you.

    Up to now, you've just been lucky that the endian of your processors has matched the endian of your data stream. So you could get away with basically memcpy

    If you want it to be truly portable, then you need to deal with each byte yourself, eg
    Code:
    void transcribePacket(AppAuxSLANPacket_t *result, uint8_t message[], uint8_t length) {
      result->deviceType = message[0];
      result->RSSI = message[1];
      result->batteryVoltage = message[2] | ( message[3] << 8 );
      result->errors = message[4] | ( message[5] << 8 );
    }
    You might have to mess about with which byte gets the <<8 treatment.

    Yes it sucks if you have lots of messages, but there's no getting round it if you want portable code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Feb 2008
    Posts
    58
    ahh ic, yes that has worked - annoying but hey - if it works...

    Just to make sure I understand what I had been reading: the Linux system is a Little endian based system and my embedded system is a big endian based system?

    cheers

    David

  5. #5
    .
    Join Date
    Nov 2003
    Posts
    307
    Linux on x86 is little endian because x86 is little endian. There can be architectures running Linux that may not be little endian.

    The Internet Protocol defines internet endianness as big endian. So Linux provides ntohs() and htons() (htonl.. ntohl too) to switch endianness in a data stream from one to the other.
    On big endian systems those functions do nothing because the endianness is already correct.

  6. #6
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    maybe this may help

  7. #7
    Registered User
    Join Date
    Feb 2008
    Posts
    58
    Thank you every one for your help, I have been playing with the htons and ntohs functions to try to get the order to reverse:

    Code:
    uint16_t var1 = 0x1234;
    	
    printf("htons: %04X | \n", htons(var1));
    printf("ntohs: %04X | \n\n", ntohs(var1));
    But neither of them seem to do anything to do the data? Am I doing something wrong?

    cheers

    David

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    ntohs() etc are wired into your machine to do the "right thing" for messages which have been created using htons()

    You can use the idea, but I think you need to create your own functions to match the endian-ess of your actual data.

    The implementation of ntons() et al WILL change if the underlying architecture Linux is running on. If you get them to work on Linux 'A', then it's back to being broken again on Linux 'B'
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Searching backwards in a string
    By Ducky in forum C++ Programming
    Replies: 11
    Last Post: 03-09-2008, 01:54 AM
  2. Question about .NET backwards compatibility
    By gunder in forum C# Programming
    Replies: 5
    Last Post: 09-15-2006, 07:08 AM
  3. Oh noes, backwards she goes!
    By cboard_member in forum C++ Programming
    Replies: 8
    Last Post: 03-11-2006, 09:58 AM
  4. Taking input and Outputting it backwards
    By whtpirate in forum C Programming
    Replies: 9
    Last Post: 06-08-2003, 10:59 AM
  5. how to print a string backwards
    By Unregistered in forum C# Programming
    Replies: 2
    Last Post: 01-27-2002, 01:04 PM