Long to Char Array and Back

I want to store a long into a character array for writing to an SD card…and then, obviously, get it back to a long! I found the below code but the long that I get back is 722 not what I put in. Since bitwise operations make my head hurt I need help badly!

    unsigned long int longInt = 1234567890;
    unsigned char byteArray[4];
              
    // convert from an unsigned long int to a 4-byte array
    byteArray[0] = (int)((longInt >> 24) & 0xFF) ;
    byteArray[1] = (int)((longInt >> 16) & 0xFF) ;
    byteArray[2] = (int)((longInt >> 8) & 0XFF);
    byteArray[3] = (int)((longInt & 0XFF));
 
    unsigned long int anotherLongInt;

    anotherLongInt = ( (byteArray[0] << 24) 
                   + (byteArray[1] << 16) 
                   + (byteArray[2] << 8) 
                   + (byteArray[3] ) );
anotherLongInt = ( ((unsigned long)byteArray[0] << 24) 
                   + ((unsigned long)byteArray[1] << 16) 
                   + ((unsigned long)byteArray[2] << 8) 
                   + ((unsigned long)byteArray[3] ) )

shouldn’t this work too?

for(int i =0; i < sizeof(byteArray); i++)
{
    anotherLongInt |= ( (long)byteArray[i]) << (i*8) );
}

You can also do:

unsigned long x=0x12345678;
byte* bytes;

bytes=(byte*)(&x); // bytes={0x78,0x56,0x34,0x12};

x=*((unsigned long*) bytes);

shouldn't this work too?

No, I don't believe so.

Thanks for the very quick responses. Am happily on to find my next problem. :)

A much easier way (as long as there are no inter-machine endian issues) is to use a union.

AWOL: Thanks for your first answer...it is what I just stuck in my code. Is there any chance I could ask for a code example of using a union? My education in bit level operations was a VERY very VERY long time ago...

The great thing about a union is that it isn't bit-level at all - just write your variable to one part of the union, and read it back from another. Useful tutorial

(BTW, I'm not entirely sure the solution I gave earlier is correct - bitwise OR would be better than addition, but I've a sneaking suspicion there's still a sign-extension issue lurking)

Here is a handy function for castinig types in c++

// safely cast between types without breaking strict aliasing rules
template<typename ReturnType, typename OriginalType>
  ReturnType alias_cast( OriginalType Variable )
    {
      union{
        OriginalType  In;
        ReturnType    Out;
      };
      In = Variable;
      return Out;
    }

Then you can use like:

unsigned long lngData = *alias_cast< unsigned long* >( bytearray );
bytearray = alias_cast< byte* >( u_Data );

Or even:

struct long_t{
  unsigned char first;
  unsigned char second;
  unsigned char third;
  unsigned char fourth;
};

unsigned lngData = 0x11223344;

Serial.print( alias_cast< long_t >( lngData ).third );

AWOL:

Your earlier answer worked..............

Wisar

Your earlier answer worked..............

...sometimes

void memrev(uint8_t array[], size_t cb)
{
    uint8_t*    pLHS = array - 1;
    uint8_t*    pRHS = array + cb;
    uint8_t     t;
    while ( ++pLHS < --pRHS )
    {
        t       = *pLHS;
        *pLHS   = *pRHS;
        *pRHS   = t;
    }
}


// ... code fragment ...

const unsigned long n   = 1234567890UL; // 0x499602D2

unsigned long       v   = n;
unsigned char*      p   = (unsigned char*)&v;
memrev(p, sizeof(v));

Serial.println(p[0], HEX);
Serial.println(p[1], HEX);
Serial.println(p[2], HEX);
Serial.println(p[3], HEX);