0

I want to be able to merge bytes from two unsigned long parameters, taking exactly half of the bytes, the half that starts with the least significant byte of the second param and the rest of the first param.

For example:

x = 0x89ABCDEF12893456 
y = 0x76543210ABCDEF19
result_merged = 0x89ABCDEFABCDEF19

First, I need to check whether the system that I work on is little endian or big endian. I already wrote a function that checks that, called is_big_endian().

now I know that char char *c = (char*) &y will give me the byte that stored at the largest memory address .

Now, I wanted to use AND(&) bitwise operator to merge x and y bytes, but I could not use it because I can't really know what is the size of the "long", it can be different for 32 or 64 bit systems, so I can't really use a fixed size.

Which means I can't use any bit masking like:

(y & 0x00000000ffffffff) | (x & 0xffffffff00000000);

I'm not allowed to use long long, uint_fast64_t or reinterpret_cast or any other "externals" things.

I was thinking about:

  1. using bytes shifting
  2. using an array to store the bits and run a loop on this array.

So I wrote this code, where I can just use the "sizeof" to find the size of the long and not to care if it's a 32 or 64 bit system.

unsigned long merge(unsigned long x, unsigned long int y)
        {
        char* charX = (char*)&x;
        char* charY = (char*)&y;
        if (is_big_endian == 0){
    // it's a little endian machine
            for (int i=0; i<(sizeof(unsigned long))/2; i++){
                *charX<<1;
                *charY>>1;
            }
        }
        else
                {
                    for (int i=0; i<(sizeof(unsigned long))/2; i++){
                    *charX>>1;
                    *charY<<1;
                }
            }
            return (x | y);
        }

I have shitfted the right side of the bits of y if that's a little endian system because the LSB there is the furthest to the left bit. And did the opposite if this is a big endian system.

But it's not working so well and the output is: 0xffffffffbbcdff5f

any help would be appreciated.

Dima Ciun
  • 87
  • 1
  • 11
  • 1
    What has endianness to do with it? The l.s. byte of a variable is always the l.s. byte. The l.s. 2 bytes are `var & 0xFFFF`. The next 2 are `var & 0xFFFF0000`. Just extract the parts like that and OR them together. – Weather Vane Nov 20 '20 at 19:30
  • because as I said, I need to know where the l.s byte is stored to be able to know the direction of the shifting. – Dima Ciun Nov 20 '20 at 19:34
  • 2
    That's irrelevant in the value of a variable, and no shifting is needed. You can find the size of the data type and set the masks accordingly. – Weather Vane Nov 20 '20 at 19:35
  • But as I said, I can't extract them because I can't know the exact size of the "long". I don't know whether the machine that is running the code is 32 or 64 bit. I need exact half of the given paramter. I can't really understand what do you mean. – Dima Ciun Nov 20 '20 at 19:38
  • 2
    The size is `sizeof(x).` If that is `4` then use masks `0xFFFF0000` and `0x0000FFFF` and similar if the size is `8`. – Weather Vane Nov 20 '20 at 19:39
  • um, so let me clear this out. Your suggestion is to stick with bit masking, and just add "if (sizeof(unsigned long) == 4) (y & 0x00000000ffffffff) | (x & 0xffffffff00000000) else....." type of thing? Would that be smart considering I'm assuming the size and giving a fixed size? – Dima Ciun Nov 20 '20 at 19:44
  • This has nothing to do with endianess. Just find the size of your type, construct a mask and do the simple math. – Support Ukraine Nov 20 '20 at 19:51
  • @4386427 that's what I said, and did, but someone thinks it's wrong. – Weather Vane Nov 20 '20 at 19:54

1 Answers1

2

The endianness is not relevant, and you can do it like this.

unsigned long merge(unsigned long x, unsigned long y)
{
    if(sizeof x == 4)
        return (x & 0xFFFF0000ul) | (y & 0x0000FFFFul);
    else
        return (x & 0xFFFFFFFF00000000ul) | (y & 0x00000000FFFFFFFFul);
}

You can also use conditional compilation

unsigned long merge(unsigned long x, unsigned long y)
{
#if ULONG_MAX == 0xFFFFFFFFul
    return (x & 0xFFFF0000ul) | (y & 0x0000FFFFul);
#else
    return (x & 0xFFFFFFFF00000000ul) | (y & 0x00000000FFFFFFFFul);
#endif
}
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • I don't know who disliked it, but it does work and seems like the right answer. I feel bad for trying so hard to avoid using masks and going on the shifting thing while I just could add the "if statement" like you did. Thanks! – Dima Ciun Nov 20 '20 at 19:56
  • The important bit was trying. – Weather Vane Nov 20 '20 at 19:57