Setting a bit
Use the bitwise OR operator (|
) to set a bit.
number |= 1UL << n;
That will set the n
th bit of number
. n
should be zero, if you want to set the 1
st bit and so on upto n-1
, if you want to set the n
th bit.
Use 1ULL
if number
is wider than unsigned long
; promotion of 1UL << n
doesn't happen until after evaluating 1UL << n
where it's undefined behaviour to shift by more than the width of a long
. The same applies to all the rest of the examples.
Clearing a bit
Use the bitwise AND operator (&
) to clear a bit.
number &= ~(1UL << n);
That will clear the n
th bit of number
. You must invert the bit string with the bitwise NOT operator (~
), then AND it.
Toggling a bit
The XOR operator (^
) can be used to toggle a bit.
number ^= 1UL << n;
That will toggle the n
th bit of number
.
Checking a bit
You didn't ask for this, but I might as well add it.
To check a bit, shift the number n to the right, then bitwise AND it:
bit = (number >> n) & 1U;
That will put the value of the n
th bit of number
into the variable bit
.
Changing the nth bit to x
Setting the n
th bit to either 1
or 0
can be achieved with the following on a 2's complement C++ implementation:
number ^= (-x ^ number) & (1UL << n);
Bit n
will be set if x
is 1
, and cleared if x
is 0
. If x
has some other value, you get garbage. x = !!x
will booleanize it to 0 or 1.
To make this independent of 2's complement negation behaviour (where -1
has all bits set, unlike on a 1's complement or sign/magnitude C++ implementation), use unsigned negation.
number ^= (-(unsigned long)x ^ number) & (1UL << n);
or
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
It's generally a good idea to use unsigned types for portable bit manipulation.
or
number = (number & ~(1UL << n)) | (x << n);
(number & ~(1UL << n))
will clear the n
th bit and (x << n)
will set the n
th bit to x
.
It's also generally a good idea to not to copy/paste code in general and so many people use preprocessor macros (like the community wiki answer further down) or some sort of encapsulation.
POSIX is a family of standards, specified by the IEEE, to clarify and make uniform the application programming interfaces (and ancillary issues, such as commandline shell utilities) provided by Unix-y operating systems.
When you write your programs to rely on POSIX standards, you can be pretty sure to be able to port them easily among a large family of Unix derivatives (including Linux, but not limited to it!); if and when you use some Linux API that's not standardized as part of Posix, you will have a harder time if and when you want to port that program or library to other Unix-y systems (e.g., MacOSX) in the future.
Best Answer
The problem you are facing is the misunderstanding of
sem_init()
function. When you read the manual page you will see this:If you are done reading up to this point, you will think that the non-zero value of pshared will make the semaphore inter-process semaphore. However, this is wrong. You should continue reading and you'll understand that you have to locate the semaphore in a shared memory region. To do that, several functions can be used as you can see below:
I find this approach as a more complicated approach than others, therefore I want to encourage people to use
sem_open()
instead ofsem_init()
.Below you can see a complete program illustrates the following:
OUTPUT
It is not bad to check
shmkey
since whenftok()
fails, it returns -1. However if you have multiple shared variables and if theftok()
function fails multiple times, the shared variables that have ashmkey
with value-1
will reside in the same region of the shared memory resulting in a change in one affecting the other. Therefore the program execution will get messy. To avoid this, it is better checked if theftok()
returns -1 or not (better to check in source code rather than printing to screen like I did, although I wanted to show you the key values in case there is a collision).Pay attention to how the semaphore is declared and initialized. It's different than what you have done in the question (
sem_t sem
vssem_t* sem
). Moreover, you should use them as they appear in this example. You cannot definesem_t*
and use it insem_init()
.