I've defined in one header file two #define with a mask:
myheader.h
#define MASK_A IPC_CREAT | IPC_EXCL | 0666
#define MASK_B 0666
void myfunction(int mymask);
myfile.c
#include "myheader.h"
...
void myfunction(int mymask) {
if (MASK_A == mymask) {
printf("My mask is A\n");
/* Do some things... */
} else {
printf("My mask is B\n");
/* Do other things...*/
}
}
void main() {
myfunction(MASK_A);
myfunction(MASK_B);
}
As far as I know, with this simple program should do first MASK_A things defined in myfunction
and after that, MASK_B things, but I don't know why, both times program goes through MASK_A way.
Cast
if ((int)MASK_A == mymask)
doesn't work.It looks like #define MASK_A and MASK_B are not being considered as integer, because:
If I redefine function as:
void myfunction(int mymask) {
int _maskA=MASK_A;
if (_maskA == mymask) {
printf("My mask is A\n");
/* Do some things... */
} else {
printf("My mask is B\n");
/* Do other things...*/
}
}
It works fine, but it doesn't look very pretty.
Anyone knows a better way to manage #define
literals and integer comparison, please?
Thanks in advance.
It doesn't work because Comparison operator (==) has Higher precedence than Bitwise Or (|). So when you do
if (MASK_A == mymask)
it results into,
if (IPC_CREAT | IPC_EXCL | 0666==mymask)
final execution is somewhat like,
if (IPC_CREAT | IPC_EXCL |( 0666==mymask))
Try defining your macro as
#define MASK_A (IPC_CREAT | IPC_EXCL | 0666)
It is advised to always parenthesise your macros
#define MASK_A (IPC_CREAT|IPC_EXCL|0666)
Especially when it comes to &
and |
, C's precedence rules
can be confusing:
#include <stdio.h>
#include <assert.h>
int main()
{
int mask = 0xAA|0xBB00; assert(mask==0xBBAA);
printf("%x\n", 0xAA|0xBB00 == mask);
//prints aa because 0xAA|(0xBB00==mask /*false==0*/) equals 0xAA
//IOW, == has a higher precedence than |
//ans so 0xAA|0xBB00==mask is equivalent to 0xAA|(0xBB00==mask)
printf("%x\n", (0xAA|0xBB00) == mask);
//prints 1 — parentheses force the intended grouping
}
As Denis Ritchie, the language's author, put it in the first K&R,
"Some of the operators have the wrong precedence; some parts of the syntax could be better."
He explains these precedences for |
and &
in his article,
The Development of the C Language* where he explains that
|
and &
were used in B
instead of the short-circuiting, logical ||
and &&
(which B didn't have and neither did prehistoric C) and so the precedence rules for |
and &
were so that:
if (a==b & c)
would be parsed as
if ((a==b) & c)
The short-circuting, logical &&
and ||
were later added, but the original precedences for |
and &
were kept.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With