Thread: Endian swap error

  1. #1
    Registered User
    Join Date
    Sep 2014
    Posts
    121

    Endian swap error

    Hello,
    I am trying to perform an endian swap using the union method:
    Code:
    #include <pthread.h>
    #include <stdio.h>
    
    typedef union
    {
        char c[sizeof(int)];
        int i;
    } buff;
    
    int endianSwap(int i)
    {
        buff eswap;
        eswap.i = i;
    
        eswap.c[0] = (8>>eswap.c[0] | eswap.c[0]<<8 );
        eswap.c[1] = (8>>eswap.c[1] | eswap.c[1]<<8 );
        eswap.c[2] = (8>>eswap.c[2] | eswap.c[2]<<8 );
        eswap.c[3] = (8>>eswap.c[3] | eswap.c[3]<<8 );
    
        return eswap.i;
    }
    
    int main(void)
    {
        int i = 1;
        printf("%d is i\n",  i);
        i = endianSwap(i);
    
    
        printf("%d  is i\n", i);
        return 0;
    }
    If I use "1" as a parameter it does not makes the ingeger that must have the rightmost bit set to 1 gives a different value? What is wrong here? I was trying to manipulate byte by byte using the union addressing. Maybe a misstake?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I think the problem is mainly with your swapping.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    Fixed the swap error but still not swaps
    Code:
    eswap.c[0] = (eswap.c[0] >> 8) | eswap.c[0]<<8 );
    ...
    I though that the union and the char array will be in the same address so I can acces 4 8 bits separately and perform 8 bit swap per array? Is that correct?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I don't understand what's with the bit shifting and bitwise or. Using a more conventional approach works for me:
    Code:
    char temp;
    
    temp = eswap.c[0];
    eswap.c[0] = eswap.c[3];
    eswap.c[3] = temp;
    
    temp = eswap.c[1];
    eswap.c[1] = eswap.c[2];
    eswap.c[2] = temp;
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Aug 2010
    Location
    Poland
    Posts
    733
    Quote Originally Posted by heatblazer View Post
    Fixed the swap error but still not swaps
    Code:
    eswap.c[0] = (eswap.c[0] >> 8) | eswap.c[0]<<8 );
    ...
    I though that the union and the char array will be in the same address so I can acces 4 8 bits separately and perform 8 bit swap per array? Is that correct?
    This expression cannot swap anything, because it does not make any use of c[3] for c[0].

  6. #6
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    You're mixing two different methods. Either use your union to swap the bytes around or use bit-shifting to move the bits around in the original object. However, bit-shifting with signed values (particularly right-shifting, I believe ... laserlight?) is not portable (different compilers could do different things).

  7. #7
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Right-shifting a signed value is only implementation-defined when it is negative.

    6.5.7 Bitwise shift operators

    5.
    The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type
    or if E1 has a signed type and a nonnegative value, the value of the result is the integral
    part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the
    resulting value is implementation-defined.

  8. #8
    Registered User
    Join Date
    Aug 2010
    Location
    Poland
    Posts
    733
    Quote Originally Posted by Matticus View Post
    Right-shifting a signed value is only implementation-defined when it is negative.
    It does not change anything - it is still not portable.

  9. #9
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Quote Originally Posted by kmdv View Post
    It does not change anything - it is still not portable.
    I did not say it was portable, I was confirming what algorism said by quoting the relevant section of the standard.

  10. #10
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    I`ve written a simple type universal macro that swaps int 16 or 32 also floats with no problem at all and works for my problems:
    Code:
    #define ENDIAN_SWAP(Type, Var)                  \
        {                                           \
        union { char c[sizeof(Type)]; Type i; }     \
        ibuff[2];                                   \
        ibuff[0].i = Var;                           \
        int j = 0;                                  \
        int h = sizeof(Type)-1;                     \
        for(; j < sizeof(Type); j++, h--)           \
        {                                           \
            ibuff[1].c[h] = ibuff[0].c[j];          \
        }                                           \
        Var =  ibuff[1].i;                          \
        }                                           \

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by heatblazer
    I`ve written a simple type universal macro that swaps int 16 or 32 also floats with no problem at all and works for my problems:
    It is advisable to do the do while (0) trick for multi-line function-style macros that require scope. Unless you use the non-standard typeof, it looks like you require the type to be passed to the macro. While I understand this may be practice with union, it seems to me that just treating the object as a sequence of bytes through a cast and then doing an in-place swap would suffice:
    Code:
    #define ENDIAN_SWAP(x) do {                   \
        char *bytes = (char*)&x;                  \
        char temp;                                \
        size_t i;                                 \
        for (i = 0; i < sizeof(x) / 2; ++i)       \
        {                                         \
            temp = bytes[i];                      \
            bytes[i] = bytes[sizeof(x) - i - 1];  \
            bytes[sizeof(x) - i - 1] = temp;      \
        }                                         \
    } while (0)
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Sep 2014
    Posts
    121
    I do agree with your solution. Thanks

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. [Big Endian vs Little Endian] Review Problem
    By Roadrunner2015 in forum C Programming
    Replies: 8
    Last Post: 02-17-2015, 12:18 AM
  2. Fiddling with the bits(Big Endian vs Little Endian)
    By A34Chris in forum C Programming
    Replies: 71
    Last Post: 11-26-2012, 10:39 PM
  3. Little endian and Bit endian advantages and disadvantages
    By nkrao123@gmail. in forum C Programming
    Replies: 4
    Last Post: 09-11-2011, 04:40 AM
  4. big endian-small endian problem
    By kapil1089thekin in forum C Programming
    Replies: 3
    Last Post: 05-15-2008, 06:47 PM
  5. Big Endian Little Endian Complex- Converting Characters
    By bd02eagle in forum C Programming
    Replies: 3
    Last Post: 07-11-2006, 01:01 AM