Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

How Do I...

Name: Anonymous 2008-08-29 13:31

...access individual bits in a byte in C++?

Name: Anonymous 2008-08-29 13:35

<< >> & ^ |
are your friends

Name: Anonymous 2008-08-29 13:36

oh and 0 and 1 of course

Name: Anonymous 2008-08-29 13:40

binary_cast

Name: Anonymous 2008-08-29 14:18

>>4
ಠ_ಠ

Name: Anonymous 2008-08-29 15:14

static String toBinaryString(int i)

Creates a string representation of the integer argument as an unsigned integer in base 2.

Name: Anonymous 2008-08-29 15:19

Name: Anonymous 2008-08-29 16:32

I'd use std::bitset, it's a robust class for handling sets of bits.

#include <iostream>
#include <sstream>
#include <iomanip>
#include <bitset>
#include <iostream>
#include <numeric>
#include <locale>

namespace bit_twiddling {
    namespace detail {
        template<class T>
        class binary_num_put_facet : public std::num_put<T> {
        public:
            iter_type do_do_put(iter_type itr, std::ios_base&, char_type fill, unsigned long val) const {
                //Gets the most significant bit for an unsigned long.
                unsigned long bit = 1 << sizeof(unsigned long) * CHAR_BIT - 1;
                while(bit) {
                    *itr++ = val & bit ? '1': '0';
                    bit >>= 1;
                }
                return itr;
            }

            iter_type do_put(iter_type itr, std::ios_base& io, char_type fill, bool v) const {
                return do_do_put(itr, io, fill, static_cast<unsigned long>(v));
            }

            iter_type do_put(iter_type itr, std::ios_base& io, char_type fill, long v) const {
                return do_do_put(itr, io, fill, static_cast<unsigned long>(v));
            }

            iter_type do_put(iter_type itr, std::ios_base& io, char_type fill, unsigned long v) const {
                return do_do_put(itr, io, fill, static_cast<unsigned long>(v));
            }

            iter_type do_put(iter_type itr, std::ios_base& io, char_type fill, long double v) const {
                return do_do_put(itr, io, fill, static_cast<unsigned long>(v));
            }

            iter_type do_put(iter_type itr, std::ios_base& io, char_type fill, const void* v) const {
                return do_do_put(itr, io, fill, reinterpret_cast<unsigned long>(v));
            }
        };

        template<class T>
        class binary_num_get_facet : public std::num_get<T> {
        public:
            template<class T>
            iter_type do_do_get(iter_type in, iter_type end, std::ios_base&, std::ios_base::iostate& err, T& val) const {
                T current = T();

                //Should start with a 1 or 0. I assume it skips whitespace for us?
                if(*in != '0' && *in != '1') {
                    //val is left unchanged.
                    err = std::ios_base::failbit;
                    return in;
                }

                while(in != end) {
                    if(*in == '1') {
                        current = (current << 1) | 1;
                    } else if(*in == '0') {
                        current <<= 1;
                    } else {
                        break;
                    }
                    ++in;
                }

                err = std::ios_base::goodbit;
                val = current;
                return in;
            }

            iter_type do_get(iter_type in, iter_type end, std::ios_base& io, std::ios_base::iostate& err, long& v) const {
                return do_do_get(in, end, io, err, v);
            }

            iter_type do_get(iter_type in, iter_type end, std::ios_base& io, std::ios_base::iostate& err, unsigned short& v) const {
                return do_do_get(in, end, io, err, v);
            }

            iter_type do_get(iter_type in, iter_type end, std::ios_base& io, std::ios_base::iostate& err, unsigned int& v) const {
                return do_do_get(in, end, io, err, v);
            }

            iter_type do_get(iter_type in, iter_type end, std::ios_base& io, std::ios_base::iostate& err, unsigned long& v) const {
                return do_do_get(in, end, io, err, v);
            }

            iter_type do_get(iter_type in, iter_type end, std::ios_base& io, std::ios_base::iostate& err, float& v) const {
                err = std::ios_base::failbit;
                return in;
            }

            iter_type do_get(iter_type in, iter_type end, std::ios_base& io, std::ios_base::iostate& err, double& v) const {
                err = std::ios_base::failbit;
                return in;
            }

            iter_type do_get(iter_type in, iter_type end, std::ios_base& io, std::ios_base::iostate& err, long double& v) const {
                err = std::ios_base::failbit;
                return in;
            }

            iter_type do_get(iter_type in, iter_type end, std::ios_base& io, std::ios_base::iostate& err, void*& v) const {
                err = std::ios_base::failbit;
                return in;
            }
        };
    }

    //TODO: add template constraints or static assertion that IntegerT really is an integer.
    template<class IntegerT>
    bool get_bit(IntegerT value, int bit) {
        std::ostringstream os;

        //BEWARE! Allocating this on the stack would have caused heap corruption.
        //std::locale::facet uses a reference counting mechanism, and will be deleted
        //when the time comes. If it is allocated on the stack, it will be deleted twice.
        std::locale bnp_locale(os.getloc(), new detail::binary_num_put_facet<char>);
        os.imbue(bnp_locale);
        os << value;

        //Now, at long last, set the Nth bit in the bitset.
        std::string str = os.str();
        std::bitset<CHAR_BIT * sizeof IntegerT> bs(str);
        return bs.test(bit);
    }

    template<class IntegerT>
    IntegerT set_bit(IntegerT value, int bit, bool set) {

        std::ostringstream os;
        std::locale bnp_locale(os.getloc(), new detail::binary_num_put_facet<char>); //Beware - see get_bit
        os.imbue(bnp_locale);
        os << value;

        //Now, at long last, set the Nth bit in the bitset.
        std::string str = os.str();
        std::bitset<CHAR_BIT * sizeof IntegerT> bs(str);
        bs.set(bit, set);

        //Read the number back from the stream using a locale with the binary num_get facet added.
        std::istringstream is(bs.to_string('0'));
        std::locale bng_locale(os.getloc(), new detail::binary_num_get_facet<char>);
        is.imbue(bng_locale);
        is >> value;
        return value;
    }
}

int main() {
    long x = 32;
    endl(std::cout << "x is " << x);
    endl(std::cout << "7th bit of x is " << bit_twiddling::get_bit(x, 7));
    endl(std::cout << "Setting 7th bit in x, please wait...");
    x = bit_twiddling::set_bit(x, 7, true);
    endl(std::cout << "x is " << x);
    endl(std::cout << "7th bit of x is " << bit_twiddling::get_bit(x, 7));
    endl(std::cout << "Unsetting 7th bit in x, please wait...");
    x = bit_twiddling::set_bit(x, 7, false);
    endl(std::cout << "x is " << x);
    endl(std::cout << "Done.");

    std::cin.get();
}


SEPPLES QUALITY!

Name: Anonymous 2008-08-29 16:48

Leave the bit twiddling to us, child.

Name: Anonymous 2008-08-29 16:50

>>8
WTF DUDE. thats just too much.

set nth bit:
x |= 1<<n;

unset nth bit:
x &= ~(1<<n);

get nth bit:
(x&(1<<n))>>n;

Name: Anonymous 2008-08-29 16:55

toggle nth bit:
x ^= 1<<n;

Name: Anonymous 2008-08-29 17:03

>>10
lrn2humor

Also, get nth bit:
(x>>n)&1;

Name: Anonymous 2008-08-29 19:49

The real question, however:

Being a portable assembly language, WHY THE FUCK CAN'T I ACCESS THE CARRY BIT IN C?!?!?  That'd make a number of bit-twiddling operations and overflow detection a hell of a lot easier!

Name: Anonymous 2008-08-29 20:26

>>13
Overflow detection is one of C's flaws. It's impossible to detect overflows in a portable way.

Type sizes being platform-dependent are another flaw.

Name: Anonymous 2008-08-29 20:43

>>13
portable

>>14
Platform dependant type sizes are a strength. They are defined well enough to be useful, but leave enough room to be impementable on all kinds of machines (including for example 36-bit ones).

Name: Anonymous 2008-08-29 21:22

>>14
I wouldn't mind the option (and actually designed a toy language) that you can specify, for instance int16 (at least 16 bits, whatever works for this platform) vs int16! (exactly 16 bits, mask off if register size is larger).  I think there's a language or two that can do this nowadays.

Name: Anonymous 2008-08-29 21:32

>>15
Yeah, fuck, you have a language with the comfort and power of a portable assembler (which is not a compliment), and you can't even be sure about the size of your ints. Since ints could be tiny somewhere, you can't use them reliably unless you waste space everywhere else. And people love to assume they're 32 bits, and shit fucks up anywhere else.

>>16
This would have been the sane thing to do in C.

Name: Anonymous 2008-08-29 21:56

Isn't short always 16 bits and long always 32 bits? Or is it different in 64-bit architectures?

Name: Anonymous 2008-08-29 22:11

>>16-17
c does have int16_t and int_least16_t...

Name: Anonymous 2008-08-29 22:30

>>16
Automatic masking seems pretty useless TBH and your `int16' already exists as short/int and as int_least16_t/int_fast16_t with <stdint.h>.

>>17
Code does not have to make assumptions about the limits of integer types; it can consult the constants from <limits.h>.

>>18
Read http://home.att.net/~jackklein/c/inttypes.html

Name: Anonymous 2008-08-30 0:21

When weill C have 128 bit integers? I need to get a more accurate calculation of Pi.

Name: Anonymous 2008-08-30 0:24

>>21
3 isn't good enough for you?

Name: Anonymous 2008-08-30 1:05

>>21
gcc supports int128_t...

Name: Anonymous 2008-08-30 1:09

>>19
>>20
I guess I used an incorrect sample.  What about int9! or int18?  Yeah, nowadays you're really going to end up with powers of 2 for bit width, but that wasn't always the case.

Name: Anonymous 2008-08-30 1:22

>>24
that wasn't always the case
I'm sorry, I've never used a toy microarchitecture. Bit twiddling1 considered harmful, etc.
                           
References: [1] http://www.cs.utk.edu/~vose/c-stuff/bithacks.html

Name: Anonymous 2008-08-30 1:24

>>21
just use GMP.

>>24
a compiler on a platform that has 9-bit and 18-bit registers would probably support int9_t and int_least18_t.

Name: Anonymous 2008-08-30 1:32

>>26
yeah, a fuckload of good that'll do if you lock in your code to one architecture.

Name: Anonymous 2008-08-30 2:06

>>27
int9_t wouldn't work anyway on most platforms, and if you're worried about portability you'd probably be better to use something like int_least16_t or int_least32_t instead of int_least18_t.

Name: Anonymous 2008-08-30 3:00

>>28
which is exactly why C fucking sucks and fails hard at shit like this.  (ergo, this thread)

Name: Anonymous 2008-08-30 5:24

>>20
Code does not have to make assumptions about the limits of integer types; it can consult the constants from <limits.h>.
Rendering integers useless. If your program has to work with the smallest integer types just in case, because you can't make assumptions on the size of integers, I guess you'd end up doing using long always and assuming no more than 16 bits.

>>25
Toy you say? Can't you see it? The second I knew older architectures had 9 or 18 bit bytes, I went like House's picture of "WANT". You know, the failure of Unicode 2.0, adding surrogate pairs to UCS2 to become UTF-16, the 21-bit Universal Character Set, the inefficient UTF-32, the early arrival of carry-based 64 bit numbers on 32 bit architectures because 4 GB is just not enough, and so many hassles wouldn't have been necessary if we had 18 bit bytes. I luv 18 bit bytes. I'm going to fap tonight to a 18/36-bit architecture. In fact, if I were back to the 60s and I were in charge of designing the architecture of the future with all I learnt from the future, I'd make it a 36 bit machine with 18 bit bytes. DO WANT.

Name: Anonymous 2008-08-30 5:32

>>30
So tell us. What's the latest architecture you've designed?

Name: Anonymous 2008-08-30 6:22

The Von Nothing Architecture

Name: Anonymous 2008-08-30 8:06

I wish Intel would hurry the fuck up with that trinary computer.

Name: Anonymous 2008-08-30 8:22

>>30
You'll need 2x the adders, etc.

Name: Anonymous 2008-08-30 8:35

>>30
long
16 bits
You are hereby disqualified from this discussion.

>>24
For an int18 you would normally just use a long (are those extra bits really gonna hurt you?), but if you insist on having the smallest sufficient type you can use the preprocessor to pick the right one.

#include <limits.h>
#include <stdio.h>

typedef
#if SCHAR_MAX >= 131071
    signed char
#elif SHORT_MAX >= 131071
    short
#elif INT_MAX >= 131071
    int
#else
    long // We know it's big enough
#endif
int18;

int main(void)
{
    printf("%d\n", CHAR_BIT * sizeof(int18));
}


It's a bit big, but it's not something you should do all the time anyway (and you could use some preprocessor tricks otherwise).

Name: Anonymous 2008-08-30 9:05

>>35
and that, my friends, is what we in the technical field call a SHITLOAD OF FUCK. ASS!

Name: Anonymous 2008-08-30 12:07

get nth bit:
(x&(1<<n))>>n;


actually, x&(1<<n) if you just want to use it as a condition, and otherwise (x>>n)&1.

Name: Anonymous 2008-08-30 12:43

Just ask for the n-th bit:

Give me the n-th bit, please, Dr. Sussman!

Name: Anonymous 2008-08-30 13:11

>>37
Actually, you're an idiot.

Name: Anonymous 2009-03-06 5:44

To quack the right   head space nothing   is worthless Do   I complain that.

Name: Anonymous 2011-02-03 2:55


Don't change these.
Name: Email:
Entire Thread Thread List