Krunk
Krunk

Reputation: 1

AND-ing shorts in c++

How would i write a piece of code that ANDs the first byte of a short, but not the second part?

Eaxmple: I have a short called inputShort, and I want this short to delete all values in the second byte. So I want to AND this with a logic operator.

Well, I tried, and I failed. so can someone give me an example how to do this ?

My goal is to keep the left part of the short, and empty out the right part of the short.

Upvotes: 0

Views: 270

Answers (6)

George
George

Reputation: 2057

In response to Krunk's comment above: First of all, you probably want to do this:

short total = tempA | tempB; 

You're logically trying to OR them, not add them. If you wanted to do this with inputShort being a pointer, that'd be pretty easy, but you might as well use a reference instead, so you don't have to mess with dereferencing a pointer. Also, you have to be careful with automatic sign extension when you're dealing with signed types. If you're doing a right-shift of a value that has the most significant bit set, you're dealing with a shift of a negative number.. Well, let me just show you an example:

short foo = -5;

Let's assume 16 bit shorts for now. In two's complement binary that's

1111 1111 1111 1011

If we right-shifted that by 1, we'd get:

1111 1111 1111 1101

That extra 1 on the left hand side is there because of sign extension. So let's walk through byte-swapping our -5 using your code:

tempA = ((1111 1111 1111 1011) & 0xff00) >> 8 so, the and operation first gives us:

1111 1111 0000 0000

Then right-shift gives us:

1111 1111 1111 1111

That's obviously not what you wanted.

One way you can do this is just use a reinterpret cast. I'm assuming there's a reason your input to swapShort is a short instead of an unsigned short? In any case, I'll leave it as a short:

//I went ahead and modified this to take a short pointer, like Krunk asked. //Also note we're assuming 16-bit shorts. This'll break on platforms where this isn't the case.

void Game::swapShort(short *inputShort)
{
    //Once we start treating it as unsigned, don't have to worry about sign extension.
    unsigned short* tmp = (reinterpret_cast<unsigned short*>(inputShort);

    unsigned short highByte = ((*tmp & 0xff00) >> 8)
    *tmp = highByte | ((*tmp & 0x00ff) << 8);

}

Or if what you're REALLY trying to do is just get this in network byte order, there's an easier way, you can use htons and ntohs:

An example would be:

unsigned short foo = 300;
//htons = host to network short
unsigned short foo_net_byte_order = htons(foo);

The good thing about using htons and its equivalents is, if you're running the code on a big-endian system, htons & ntohl are basically no-ops, but it'll actually swap them on a little endian system. That is, you don't have to figure out the endianness of the system you're running on before figuring out if you need to swap or not. htons knows what network byte order means and what your host byte order is, and it will just handle it for you. There are equivalents for longs as well. See http://msdn.microsoft.com/en-us/library/ms738557%28VS.85%29.aspx

The same function exists on POSIX type operating systems as well, but you'll have to include a different set of headers.

Upvotes: 0

Krunk
Krunk

Reputation: 1

Ok, I wrote this method:

short Game::swapShort(short inputShort)
{
    short tempA;
    short tempB;

    tempA = ((inputShort & 0xff00) >> 8);
    tempB = ((inputShort & 0x00ff) << 8);

    short total = tempA + tempB;
    return total;
}

which i think should work correctly.

However, my inputShort will be a pointer in my program. Can someone also explain to me how i would adapt my method to work with short pointers? :$

Upvotes: 0

Steve Jessop
Steve Jessop

Reputation: 279315

"First" and "second" are ambiguous. They tend to refer to the storage, so endian-ness comes into play, and I assume you don't mean that. Also the number of bytes in a short is implementation-defined.

I assume you want to zero out the least significant ("right") bits, and retain all other bits:

#include <limits>

...

inputShort & ~std::numeric_limits<unsigned char>::max();

Or if you're feeling brave, and you want to assume 8-bit bytes:

inputShort & ~0xFF;

(It doesn't take very much bravery to assume 8-bit bytes).

Upvotes: 7

gnud
gnud

Reputation: 78568

I don't know if you mean the most or least significant when you say "second byte", but here is an example that might help.

short second = 0xFF00;
short first = 0x00FF;
short number = 0x1234;
short tmp;

tmp = number & first; //tmp is set to 0x1234&0x00FF -> 0x0034
tmp = number & second; //tmp is set to 0x1234&0xFF00 -> 0x1200

Upvotes: 7

Jack
Jack

Reputation: 133609

It's easy: res = inputShort & 0xff00

If you want you can also shift the second byte to the lower order one by using >>:

unsigned short res = (inputShort & 0xff00) >> 8

Upvotes: 3

Sinan &#220;n&#252;r
Sinan &#220;n&#252;r

Reputation: 118148

Assuming 16-bit shorts:

#include<stdio.h>

int main(void) {
    unsigned short val = 0xbaba;
    unsigned short mask = 0xff00;
    unsigned short result = val & mask;
    printf("%04x\n", result);
    return 0;
}

Output:

E:\tmp> t
ba00

Upvotes: 2

Related Questions