Reputation: 770
How do I write to a single bit? I have a variable that is either a 1 or 0 and I want to write its value to a single bit in a 8-bit reg
variable.
I know this will set a bit:
reg |= mask; // mask is (1 << pin)
And this will clear a bit:
reg &= ~mask; // mask is (1 << pin)
Is there a way for me to do this in one line of code, without having to determine if the value is high or low as the input?
Upvotes: 4
Views: 24455
Reputation: 9
//Through Macro we can do set resset Bit
#define set(a,n) a|=(1<<n);
#define reset(a,n) a&=(0<<n);
//toggle bit value given by the user
#define toggle(a,n) a^=(1<<n);
int a,n;
int main()
{
printf("Set Reset particular Bit given by User ");
scanf("%d %d",&a,&n);
int b =set(a,n) //same way we can call all the macro
printf("%d",b);
return 0;
}
Upvotes: 1
Reputation: 2993
Duplicate of how do you set, clear, and toggle a single bit and I'll repost my answer too as no-one's mentioned SET and CLEAR registers yet:
As this is tagged "embedded" I'll assume you're using a microcontroller. All of the above suggestions are valid & work (read-modify-write, unions, structs, etc.).
However, during a bout of oscilloscope-based debugging I was amazed to find that these methods have a considerable overhead in CPU cycles compared to writing a value directly to the micro's PORTnSET / PORTnCLEAR registers which makes a real difference where there are tight loops / high-frequency ISR's toggling pins.
For those unfamiliar: In my example, the micro has a general pin-state register PORTn which reflects the output pins, so doing PORTn |= BIT_TO_SET results in a read-modify-write to that register.
However, the PORTnSET / PORTnCLEAR registers take a '1' to mean "please make this bit 1" (SET) or "please make this bit zero" (CLEAR) and a '0' to mean "leave the pin alone". so, you end up with two port addresses depending whether you're setting or clearing the bit (not always convenient) but a much faster reaction and smaller assembled code.
Upvotes: 0
Reputation: 1421
One overlooked feature of C is bit packing, which is great for embedded work. You can define a struct
to access each bit individually.
typedef struct
{
unsigned char bit0 : 1;
unsigned char bit1 : 1;
unsigned char bit2 : 1;
unsigned char bit3 : 1;
unsigned char bit4 : 1;
unsigned char bit5 : 1;
unsigned char bit6 : 1;
unsigned char bit7 : 1;
} T_BitArray;
The : 1
tells the compiler that you only want each variable to be 1 bit long. And then just access the address that your variable reg
sits on, cast it to your bit array and then access the bits individually.
((T_BitArray *)®)->bit1 = value;
®
is the address of your variable. ((T_BitArray *)®)
is the same address, but now the complier thinks of it as a T_BitArray
address and ((T_BitArray *)®)->bit1
provides access to the second bit. Of course, it's best to use more descriptive names than bit1
Upvotes: 2
Reputation: 93870
Because you tagged this with embedded I think the best answer is:
if (set)
reg |= mask; // mask is (1 << pin)
else
reg &= ~mask; // mask is (1 << pin)
(which you can wrap in a macro or inline function). The reason being that embedded architectures like AVR have bit-set and bit-clear instructions and the cost of branching is not high compared to other instructions (as it is on a modern CPU with speculative execution). GCC can identify the idioms in that if
statement and produce the right instructions. A more complex version (even if it's branchless when tested on modern x86) might not assemble to the best instructions on an embedded system.
The best way to know for sure is to disassemble the results. You don't have to be an expert (especially in embedded environments) to evaluate the results.
Upvotes: 2
Reputation: 13196
I think what you're asking is if you can execute a write instruction on a single bit without first reading the byte that it's in. If so, then no, you can't do that. Has nothing to do with the C language, just microprocessors don't have instructions that address single bits. Even in raw machine code, if you want to set a bit you have to read the byte it's in, change the bit, then write it back. There's just no other way to do it.
Upvotes: 0
Reputation: 145899
Assuming value
is 0
or 1
:
REG = (REG & ~(1 << pin)) | (value << pin);
I use REG
instead of register
because as @KerrekSB pointed out in OP comments, register
is a C keyword.
The idea here is we compute a value of REG
with the specified bit cleared and then depending on value
we set the bit.
Upvotes: 10