# extracting front bits from an unsigned long long?

Discussion in 'C Programming' started by Digital Puer, Nov 11, 2005.

1. ### Digital PuerGuest

Hi, suppose I have an unsigned long long. I would like to extract
the front 'n' bits of this value and convert them into an integer.
For example, if I extract the first 3 bits, I would get an int between

I can assume the largest returned value fits in an int. Also,
I'm on a big-endian PPC (AIX), in case that matters.

Ideally, I'd like to implement a prototype like:
int extractFrontBits(unsigned long long value, int num_bits);

Digital Puer, Nov 11, 2005

2. ### peteGuest

Digital Puer wrote:
>
> Hi, suppose I have an unsigned long long. I would like to extract
> the front 'n' bits of this value and convert them into an integer.
> For example, if I extract the first 3 bits, I would get an int between

int three_bits = long_long_value & 7;

--
pete

pete, Nov 11, 2005

3. ### Guest

Digital Puer wrote:
> Hi, suppose I have an unsigned long long. I would like to extract
> the front 'n' bits of this value and convert them into an integer.
> For example, if I extract the first 3 bits, I would get an int between
>
> I can assume the largest returned value fits in an int. Also,
> I'm on a big-endian PPC (AIX), in case that matters.
>
> Ideally, I'd like to implement a prototype like:
> int extractFrontBits(unsigned long long value, int num_bits);

I'm guessing long long is 64 bits? Regardless, the following should
work:

frontbits = (original_value >> (sizeof(long long) - 3)) & 0x03;

The masking at the end is to zero out the msb of the result since on
some systems it doesn't get zeroed.

If number of bits is not fixed, then it would look something like the
following:

frontbits = original_value >> (sizeof(long long) - num_bits);

but the masking will get complicated.

, Nov 11, 2005
4. ### peteGuest

wrote:
>
> Digital Puer wrote:
> > Hi, suppose I have an unsigned long long. I would like to extract
> > the front 'n' bits of this value and convert them into an integer.
> > For example, if I extract the first 3 bits,
> > I would get an int between

> I'm guessing long long is 64 bits? Regardless, the following should
> work:

> frontbits = (original_value >> (sizeof(long long) - 3)) & 0x03;

You're getting 2 bits from the middle of the value.
Anything & 3, ain't going to get you more than 2 bits.
You shift the original value to the right
and the low order bits disappear.

--
pete

pete, Nov 11, 2005
5. ### peteGuest

pete wrote:
>
> Digital Puer wrote:
> >
> > Hi, suppose I have an unsigned long long. I would like to extract
> > the front 'n' bits of this value and convert them into an integer.
> > For example, if I extract the first 3 bits,
> > I would get an int between

>
> int three_bits = long_long_value & 7;

n bits, ... hmm ...

long_long_value & ((1ULL << n) - 1)

--
pete

pete, Nov 11, 2005
6. ### Barry SchwarzGuest

On 10 Nov 2005 16:59:21 -0800, "Digital Puer"
<> wrote:

>Hi, suppose I have an unsigned long long. I would like to extract
>the front 'n' bits of this value and convert them into an integer.
>For example, if I extract the first 3 bits, I would get an int between
>
>I can assume the largest returned value fits in an int. Also,
>I'm on a big-endian PPC (AIX), in case that matters.
>
>Ideally, I'd like to implement a prototype like:
>int extractFrontBits(unsigned long long value, int num_bits);

Shift the value in the variable to the right
(sizeof(unsigned long long)*CHAR_BIT - n)
bits. The result is the integer you requested.

<<Remove the del for email>>

Barry Schwarz, Nov 11, 2005
7. ### Keith ThompsonGuest

"Digital Puer" <> writes:
> Hi, suppose I have an unsigned long long. I would like to extract
> the front 'n' bits of this value and convert them into an integer.
> For example, if I extract the first 3 bits, I would get an int between

What do you mean by "front" bits?

--
Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Keith Thompson, Nov 11, 2005
8. ### Guest

pete wrote:
> wrote:
> >
> > Digital Puer wrote:
> > > Hi, suppose I have an unsigned long long. I would like to extract
> > > the front 'n' bits of this value and convert them into an integer.
> > > For example, if I extract the first 3 bits,
> > > I would get an int between

>
> > I'm guessing long long is 64 bits? Regardless, the following should
> > work:

>
> > frontbits = (original_value >> (sizeof(long long) - 3)) & 0x03;

>
> You're getting 2 bits from the middle of the value.
> Anything & 3, ain't going to get you more than 2 bits.
> You shift the original value to the right
> and the low order bits disappear.
>
> --
> pete

Ah, sorry, it should be:

frontbits = (original_value >> (sizeof(long long) - 3)) & 0x07;

, Nov 11, 2005
9. ### peteGuest

wrote:
>
> pete wrote:
> > wrote:
> > >
> > > Digital Puer wrote:
> > > > Hi, suppose I have an unsigned long long.
> > > > I would like to extract
> > > > the front 'n' bits of this value and convert them
> > > > into an integer.
> > > > For example, if I extract the first 3 bits,
> > > > I would get an int between

> >
> > > I'm guessing long long is 64 bits?
> > > Regardless, the following should
> > > work:

> >
> > > frontbits =
> > > (original_value >> (sizeof(long long) - 3)) & 0x03;

> >
> > You're getting 2 bits from the middle of the value.
> > Anything & 3, ain't going to get you more than 2 bits.
> > You shift the original value to the right
> > and the low order bits disappear.

> Ah, sorry, it should be:
>
> frontbits = (original_value >> (sizeof(long long) - 3)) & 0x07;

Barry Schwarz also seems to think that shifting the original
value to the right, is the right thing to do.
I don't get it.

I'll assume you think that CHAR_BIT is 8.
That makes your 64 bit bit long long, 8 bytes in size.
8 - 3 is two, so you shift your unsigned long long
two bits to the right, which is equivalent to dividing by 4,
and then you take the 3 lower order bits.
What is that?

--
pete

pete, Nov 11, 2005
10. ### peteGuest

Digital Puer wrote:
>
> Hi, suppose I have an unsigned long long. I would like to extract
> the front 'n' bits of this value and convert them into an integer.
> For example, if I extract the first 3 bits, I would get an int between
>
> I can assume the largest returned value fits in an int. Also,
> I'm on a big-endian PPC (AIX), in case that matters.
>
> Ideally, I'd like to implement a prototype like:
> int extractFrontBits(unsigned long long value, int num_bits);

int extractFrontBits(unsigned long long value, int num_bits)
{
return (int)(value & ((1ULL << num_bits) - 1))
}

--
pete

pete, Nov 11, 2005
11. ### Guest

pete wrote:
> I'll assume you think that CHAR_BIT is 8.
> That makes your 64 bit bit long long, 8 bytes in size.
> 8 - 3 is two, so you shift your unsigned long long
> two bits to the right, which is equivalent to dividing by 4,
> and then you take the 3 lower order bits.
> What is that?
>

Sorry again, Barry got it right, multiply with CHAR_BIT. I forgot that
part.

> Barry Schwarz also seems to think that shifting the original
> value to the right, is the right thing to do.
> I don't get it.
>

I think he's also a hardware guy, the first few bits to us are the msb.
We feel last (as in last few bits) and least (as in lsb) are
equivalent. So it follows that first and most are equivalent.

BTW, does C make any guarantees that the code works both endianness? I
have worked with compilers where shifting didn't do what I expected
because the machine was little endian. The OP would not have this
problem since he's running AIX on what I assume is either Power or
PowerPC.

Hardware guys tend to think in big-endian while software guys tend to
be little-endian. We like things big

, Nov 11, 2005
12. ### SumanGuest

pete wrote:

> I'll assume you think that CHAR_BIT is 8.
> That makes your 64 bit bit long long, 8 bytes in size.
> 8 - 3 is two, ...

[ ...]

> What is that?

Exactly! Beats me.

Suman, Nov 11, 2005
13. ### Peter NilssonGuest

Barry Schwarz wrote:
> "Digital Puer" <> wrote:
> >Hi, suppose I have an unsigned long long. I would like to extract
> >the front 'n' bits of this value and convert them into an integer.
> >For example, if I extract the first 3 bits, I would get an int between
> >
> >I can assume the largest returned value fits in an int. Also,
> >I'm on a big-endian PPC (AIX), in case that matters.
> >
> >Ideally, I'd like to implement a prototype like:
> >int extractFrontBits(unsigned long long value, int num_bits);

>
> Shift the value in the variable to the right

The OP hasn't said what 'front' bits are, but...

> (sizeof(unsigned long long)*CHAR_BIT - n)
> bits. The result is the integer you requested.

That assumes that unsigned long long isn't padded. The following
doesn't...

value / ((-1ull >> num_bits) + 1)

....although it does assume that num_bits is non-zero and less than the
width of unsigned
long long.

--
Peter

Peter Nilsson, Nov 11, 2005
14. ### Jack KleinGuest

On 10 Nov 2005 20:38:54 -0800, ""
<> wrote in comp.lang.c:

> pete wrote:
> > I'll assume you think that CHAR_BIT is 8.
> > That makes your 64 bit bit long long, 8 bytes in size.
> > 8 - 3 is two, so you shift your unsigned long long
> > two bits to the right, which is equivalent to dividing by 4,
> > and then you take the 3 lower order bits.
> > What is that?
> >

>
> Sorry again, Barry got it right, multiply with CHAR_BIT. I forgot that
> part.
>
>
> > Barry Schwarz also seems to think that shifting the original
> > value to the right, is the right thing to do.
> > I don't get it.
> >

>
> I think he's also a hardware guy, the first few bits to us are the msb.
> We feel last (as in last few bits) and least (as in lsb) are
> equivalent. So it follows that first and most are equivalent.
>
> BTW, does C make any guarantees that the code works both endianness? I
> have worked with compilers where shifting didn't do what I expected
> because the machine was little endian. The OP would not have this
> problem since he's running AIX on what I assume is either Power or
> PowerPC.

I don't know what you expected, or what you did, but shifts of
unsigned types in C are defined by value, and are completely
independent of endianness. This assumes the shift amount is not less
than 0 and is less than the width of the unsigned type in bits.

Given unsigned long l = 0x12345678, then:

l & 0xff is 0x78
(l >> 8) & 0xff is 0x56
(l >> 16) & 0xff is 0x34
(l >> 24) & 0xff is 0x12

Shifting unsigned types in C is always exactly defined, and has
nothing at all to do with endianness. Your problem was caused by
something else.

> Hardware guys tend to think in big-endian while software guys tend to
> be little-endian. We like things big

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

Jack Klein, Nov 11, 2005
15. ### Guest

Jack Klein wrote:
> I don't know what you expected, or what you did, but shifts of
> unsigned types in C are defined by value, and are completely
> independent of endianness. This assumes the shift amount is not less
> than 0 and is less than the width of the unsigned type in bits.
>
> Given unsigned long l = 0x12345678, then:
>
> l & 0xff is 0x78
> (l >> 8) & 0xff is 0x56
> (l >> 16) & 0xff is 0x34
> (l >> 24) & 0xff is 0x12
>
> Shifting unsigned types in C is always exactly defined, and has
> nothing at all to do with endianness. Your problem was caused by
> something else.
>

OK, that's what I'd expect. But, does

0x12345678 == 305419896

or

0x12345678 == 2018915346

If the number is in hex and output in hex then of course it always
works. But I was expecting something like:

(305419896 >> 16) & 0xff == 52

Maybe its just the compiler I was using since it works fine in gcc. I
expect fully conforming compilers treats hex numbers as real
"big-endian" representation of a number.

, Nov 11, 2005
16. ### Michael MairGuest

wrote:
> Jack Klein wrote:
>
>>I don't know what you expected, or what you did, but shifts of
>>unsigned types in C are defined by value, and are completely
>>independent of endianness. This assumes the shift amount is not less
>>than 0 and is less than the width of the unsigned type in bits.
>>
>>Given unsigned long l = 0x12345678, then:
>>
>> l & 0xff is 0x78
>> (l >> 8) & 0xff is 0x56
>> (l >> 16) & 0xff is 0x34
>> (l >> 24) & 0xff is 0x12
>>
>>Shifting unsigned types in C is always exactly defined, and has
>>nothing at all to do with endianness. Your problem was caused by
>>something else.

>
> OK, that's what I'd expect. But, does
>
> 0x12345678 == 305419896
>
> or
>
> 0x12345678 == 2018915346
>
> If the number is in hex and output in hex then of course it always
> works.

No! It _always_ works.
In base B, the number represented by the digits
n_k n_{k-1} ... n_0
always means n_0 * B^0 + n_1 * B^1 + ... + n_k * B^k,
so 0x12345678 clearly is 8 + 7*16 + ... = 305419896
As 0x... means unsigned, we have a guarantee how the internal
representation will look, i.e. the above _always_ works

> But I was expecting something like:
>
> (305419896 >> 16) & 0xff == 52

So what? 0x34 == 52U

> Maybe its just the compiler I was using since it works fine in gcc. I
> expect fully conforming compilers treats hex numbers as real
> "big-endian" representation of a number.

Whatever this is supposed to mean for machines with CHAR_BIT == 18

-Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.

Michael Mair, Nov 11, 2005
17. ### CoLGuest

Digital Puer wrote:
> Hi, suppose I have an unsigned long long. I would like to extract
> the front 'n' bits of this value and convert them into an integer.
> For example, if I extract the first 3 bits, I would get an int between
>
> I can assume the largest returned value fits in an int. Also,
> I'm on a big-endian PPC (AIX), in case that matters.
>
> Ideally, I'd like to implement a prototype like:
> int extractFrontBits(unsigned long long value, int num_bits);

Try this I think this solves your problem.

unsigned long int original_value=0xffffffff; //could be what ever
int frontbits=0;
int n=3; //suppose we want to extract front 3 bits
frontbits = (original_value >> (sizeof(long int )*8 - n)) & -1;

This works fine on all machines(e.g intel series, sparc, powerpc) which
use 2's complement represent negative numbers.

Regards,
Apoorv

CoL, Nov 11, 2005
18. ### Guest

Michael Mair wrote:
> No! It _always_ works.

If the compiler follows C standards. As I said before, I HAVE used a
compiler where this is not the case. But that is outside the scope of
c.l.c of course.

> > But I was expecting something like:
> >
> > (305419896 >> 16) & 0xff == 52

>
> So what? 0x34 == 52U

Yes. That's what I expected. What's with your "so what" ?

, Nov 11, 2005
19. ### peteGuest

wrote:
>
> pete wrote:
> > I'll assume you think that CHAR_BIT is 8.
> > That makes your 64 bit bit long long, 8 bytes in size.
> > 8 - 3 is two, so you shift your unsigned long long
> > two bits to the right, which is equivalent to dividing by 4,
> > and then you take the 3 lower order bits.
> > What is that?
> >

>
> Sorry again, Barry got it right, multiply with CHAR_BIT. I forgot that
> part.
>
> > Barry Schwarz also seems to think that shifting the original
> > value to the right, is the right thing to do.
> > I don't get it.
> >

>
> I think he's also a hardware guy,
> the first few bits to us are the msb.
> We feel last (as in last few bits) and least (as in lsb) are
> equivalent. So it follows that first and most are equivalent.

If Value is the identifier of an object
declared as usigned long long and you wanted to see if
Value was odd, it would be (Unsigned_Value & 1).
Where bits and bytes of the object are stored
has got nothing to do with it.

--
pete

pete, Nov 11, 2005
20. ### peteGuest

Suman wrote:
>
> pete wrote:
>
> > I'll assume you think that CHAR_BIT is 8.
> > That makes your 64 bit bit long long, 8 bytes in size.
> > 8 - 3 is two, ...

>
> [ ...]
>
> > What is that?

>
> Exactly! Beats me.

I should have used a calculator.

--
pete

pete, Nov 11, 2005