Program to toggle nth bit in C

B

Ben C

Hi,

Can anyone please tell me how to toggle a nth bit. For example, I am
having a variable which is of 8 bits. I want to toggle the nth bit.

var ^= (1U << n);

should do it

Sometimes you see flags done like this:

uint32_t set_flags(uint32_t flags, uint32_t clear, uint32_t xor)
{
return (flags & ~clear) ^ xor;
}

This odd-looking function allows you to set, toggle and clear any
combination of flags in one go, as the example below illustrates a bit.

Whether this is more or less confusing I'm not sure... it's quite good
in APIs, though, where the fact that flags are stored as bits is not
necessarily exposed to the caller.

#include <stdio.h>
#include <stdint.h>

uint32_t set_flags(uint32_t flags, uint32_t clear, uint32_t xor)
{
return (flags & ~clear) ^ xor;
}

#define APPLES 1U
#define PEARS 1U << 1
#define ORANGES 1U << 2
#define BANANAS 1U << 3

void print_flags(uint32_t flags)
{
if (flags & APPLES) printf("APPLES\n");
if (flags & PEARS) printf("PEARS\n");
if (flags & ORANGES) printf("ORANGES\n");
if (flags & BANANAS) printf("BANANAS\n");
printf("\n");
}

int main(void)
{
uint32_t flags = APPLES | ORANGES;
print_flags(flags);

/* set PEARS */
flags = set_flags(flags, PEARS, PEARS);
print_flags(flags);

/* clear PEARS */
flags = set_flags(flags, PEARS, 0);
print_flags(flags);

/* toggle PEARS a couple of times */
flags = set_flags(flags, 0, PEARS);
print_flags(flags);
flags = set_flags(flags, 0, PEARS);
print_flags(flags);

/*
* set BANANAS, toggle PEARS and APPLES, and clear ORANGES, all in one go
*/
flags = set_flags(flags, ORANGES | BANANAS, BANANAS | PEARS | APPLES);
print_flags(flags);

return 0;
}
 
R

Richard Heathfield

Ben C said:

#include <stdio.h>
#include <stdint.h>

uint32_t set_flags(uint32_t flags, uint32_t clear, uint32_t xor)
{
return (flags & ~clear) ^ xor;
}

Careful. This code can be broken by the inclusion of <iso646.h>, because of
the xor identifier.
 
C

CBFalconer

Richard said:
(e-mail address removed) said:

Let's look at something from that site, then, shall we?

----
BYTE b = 50;
BYTE c = b | 0x04;
cout << "c = " << c << endl;

This would result in the following calculation
00110010 - b
| 00000100 - | 0x04
----------
00110110 - result
----

Not only does the explanation assume that their (undefined) BYTE
type is synonymous with a byte (which, to be fair, it could be,
using a typedef to unsigned char), but it also assumes that a
byte comprises only eight bits, which is certainly false on some
systems. It also completely fails to mention the diagnostic
message that a conforming implementation must issue for the code
fragment cited above.

Which also does some very peculiar shift operations for the C
language. I have no idea whether left shifts are evaluated left to
right or right to left, nor do I intend to bother to find out. The
values of cout and endl are also undefined.
 
N

nsimeonov

I'm amazed how much efforts you guys put to answer this simple question
and defend the original poster. I was in a bad mood this morning and
that's why I answered initially, nevertheless I would be happier to see
answers to the real questions where you can't find the answer by
googling for 10 min or so.

Regards and I hope the OP actually understood the point I was making,
Nikolay
 
R

Richard Heathfield

(e-mail address removed) said:
I'm amazed how much efforts you guys put to answer this simple question
and defend the original poster.

Had you not attacked him, we would not have felt obliged to defend him. Your
attack was unwarranted and ugly.
I was in a bad mood this morning and that's why I answered initially,

Then you might want to give some consideration to the idea of waiting until
you are in a good mood before answering questions.
nevertheless I would be happier to see
answers to the real questions where you can't find the answer by
googling for 10 min or so.

We answer what gets asked. If the question is answered in the FAQ or in K&R
we will generally point the questioner in that direction. It is possible to
do this without calling him stupid.
Regards and I hope the OP actually understood the point I was making,

Presumably you mean this point: "I'm tempted to suggest you a carreer change
or plainly tell you how big of an id**t you are."

Yes, I think it would be quite difficult to misunderstand that point,
despite the appalling spelling and grammar.

If you meant the rest of your article, including that ridiculously broken
Web site you recommended, I've already dealt with that elsethread.
 
W

Walter Roberson

Can anyone please tell me how to toggle a nth bit. For example, I am
having a variable which is of 8 bits. I want to toggle the nth bit.

Which bit is the nth bit? Does the numbering start from 0 or 1?
Is the ordering left to right or right to left? Is the variable
signed or unsigned?

You should keep in mind that variables may contain padding bits and that
there might be a seperate sign bit which is not arithmetically accessible.
For example, setting the "8th" (most significant) bit of an unsigned char
is not necessarily going to result in a bit representation that
would indicate a negative number of reinterpreted as a signed value.
 
B

Ben C

Ben C said:



Careful. This code can be broken by the inclusion of <iso646.h>, because of
the xor identifier.

Good point! Maybe it's time I changed my syntax file to highlight those
things.

I did know you could use "and" and "or" etc. in C++, where I think they
may be part of the actual language syntax, not macros, but I'd not heard
of this iso646 thing.
 
F

Frederick Gotham

Walter Roberson posted:
Which bit is the nth bit? Does the numbering start from 0 or 1?


We're dealing with computers, so 0.

Is the ordering left to right or right to left? Is the variable
signed or unsigned?


An educated guess would be that the bist are indexed in ascending order,
starting with the least significant bit.

You should keep in mind that variables may contain padding bits


Unsigned integer types don't contain padding. They may however contain
trapping bits, which are bits which do not take part in the value
representation of the object.

and
that there might be a seperate sign bit which is not arithmetically
accessible.


I would have thought that there be some sort of requirement that the
signed and unsigned forms of a particular integer type have the same
amount of value representation bits... but it looks like "signed char"
can have trapping bits. (In C++, signed char cannot have trapping bits).


Well, if signed char couldn't have trapping bits in C, then the following
would be true:


(Assuming CHAR_BIT == 8)

unsigned char uc = 133;

signed char c = *( (signed char*)&uc );


Then depending on the negative number system in use, "c" can have one of
three values:

Sign-magnitude: -5
One's complement: 122
Two's complement: 123
 
F

Frederick Gotham

Frederick Gotham posted:

Sign-magnitude: -5
One's complement: 122
Two's complement: 123


I left out the negative signs:


Sign-magnitude: -5
One's complement: -122
Two's complement: -123
 
P

pete

Frederick Gotham wrote:
Unsigned integer types don't contain padding.

N869
6.2.6.2 Integer types
[#1] For unsigned integer types other than unsigned char,
the bits of the object representation shall be divided into
two groups: value bits and padding bits (there need not be
any of the latter).
 
F

Frederick Gotham

pete posted:
Frederick said:
Unsigned integer types don't contain padding.

N869
6.2.6.2 Integer types
[#1] For unsigned integer types other than unsigned char,
the bits of the object representation shall be divided into
two groups: value bits and padding bits (there need not be
any of the latter).


Okay, so they contain padding.

My understanding was that padding is required so that a type's alignment
requirements can be satisfied -- I didn't think the term extended to refer
to the "extra bits" in an unsigned integer type. Anyway I stand corrected.

Would anyone like to offer an explanation as to why an unsigned integer
type would need "padding" within it? At the moment I don't see a reason.
 
K

Keith Thompson

Frederick Gotham said:
Would anyone like to offer an explanation as to why an unsigned integer
type would need "padding" within it? At the moment I don't see a reason.

I posted an example elsewhere in this thread. The machine in
question, as I understand it, happens to have instructions that work
on a subset of the bits of a word. (The machine's design strongly
emphasizes floating-point performance; it's a Cray Y-MP.)
 
C

CBFalconer

Frederick said:
.... snip ...

Would anyone like to offer an explanation as to why an unsigned
integer type would need "padding" within it? At the moment I don't
see a reason.

Just as a couple of examples, to detect uninitialized values, or to
provide ECC correction of values.
 
K

Keith Thompson

Keith Thompson said:
I posted an example elsewhere in this thread. The machine in
question, as I understand it, happens to have instructions that work
on a subset of the bits of a word. (The machine's design strongly
emphasizes floating-point performance; it's a Cray Y-MP.)

Correction: the example was in the "FAQ-Question" thread.
 
O

Old Wolf

Frederick said:
void ToggleBit( char * const p, unsigned const bit_index )
{
*p ^= 1U << bit_index;
}

Toggling the sign bit could cause a trap representation;
you should use unsigned types when maniplating bits.
 
O

Old Wolf

int result = flags ^ (1 << bit_to_toggle);

So HOW HARD it is to figure it out from the article I initially
pointed.

Maybe you should consider a career change (unless you
are a drill sergeant or something).
 
N

Neil

Hi,

Can anyone please tell me how to toggle a nth bit. For example, I am
having a variable which is of 8 bits. I want to toggle the nth bit.

Regards,
Santosh

Look up Exclusive OR
 
O

osmium

Neil said:
Look up Exclusive OR

And by just what mystical process is Santosh supposed to know that he should
read a new message that sprouts up with the message title "XOR"?

If he had been reading *all* the messages, for a few days he probably
wouldn't have had any need to post the question he asked in the first place.
 
W

Walter Roberson

Walter Roberson posted:
We're dealing with computers, so 0.

The OP asked about the "nth" bit. "nth" is an expression indicating
an ordinal number, and ordinal numbers start with 1 -- 1st,
2nd, 3rd, 4th, etc..
An educated guess would be that the bist are indexed in ascending order,
starting with the least significant bit.

One could make that "educated guess", yes, but it does not necessarily
match the OP's requirements, as there are important processors that number
the bits the other way around.

Unsigned integer types don't contain padding.

Someone else already quoted the standard on this.

I would have thought that there be some sort of requirement that the
signed and unsigned forms of a particular integer type have the same
amount of value representation bits... but it looks like "signed char"
can have trapping bits. (In C++, signed char cannot have trapping bits).

The OP wasn't particularily firm on the point of the value being
8 bits wide, so it seemed likely to me that the OP would want to
generalize to wider types that do not have the exemptions that
various char might have.
 
F

Frederick Gotham

Old Wolf posted:
Toggling the sign bit could cause a trap representation;
you should use unsigned types when maniplating bits.


You're right. Got to get out of my C++ habit of using char all the time
rather than unsigned char. Give me a slap if I do it again!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top