Flags

A

Alexis Gatt

Hi guys,

I was reading the source code of a lib, and I came across this odd way
of defining flags

#define PHONG_RV (0<<0)
#define PHONG_NH (1<<0)

Here is how they're used:

##### START CODE #####

BRDF *Phong_BRDF::Create_Phonglike(const char *params,
                        int Phong_Flags=PHONG_PHONG)
{
// some code

        if (strcasecmp(flag1,"rv") == 0)
            Phong_Flags |= PHONG_RV;

##### END CODE #####


Could someone please explain me how they work please?

Many thanks

Alexis
 
R

ravinderthakur

#define PHONG_RV (0<<0)
#define PHONG_NH (1<<0)

these flags simply evalueate to 0 and 1 respectively. so at every place
that
PHONG_RV and PHONG_NH are used they are replaced by 0 and 1 .

BTW can't understand from where this PHONG_PHONG came from!!!


thanks
rt
 
K

Karl Heinz Buchegger

Alexis said:
Hi guys,

I was reading the source code of a lib, and I came across this odd way
of defining flags

#define PHONG_RV (0<<0)
#define PHONG_NH (1<<0)

Here is how they're used:

##### START CODE #####

BRDF *Phong_BRDF::Create_Phonglike(const char *params,
int Phong_Flags=PHONG_PHONG)
{
// some code

if (strcasecmp(flag1,"rv") == 0)
Phong_Flags |= PHONG_RV;

##### END CODE #####

Could someone please explain me how they work please?

<< appplied to integers is know as the 'bitshift left' operator

y << x
The bit pattern of y is shifted left by x bits


number bit pattern << 1 new number
(16 bits assumed)

0 0000000000000000 0000000000000000 0
1 0000000000000001 0000000000000010 2
2 0000000000000010 0000000000000100 4
3 0000000000000011 0000000000000110 6
4 0000000000000100 0000000000001000 8
5 0000000000000101 0000000000001010 10
...

number bit pattern << 2 new number
(16 bits assumed)

0 0000000000000000 0000000000000000 0
1 0000000000000001 0000000000000100 4
2 0000000000000010 0000000000001000 8
3 0000000000000011 0000000000001100 12
4 0000000000000100 0000000000010000 16
5 0000000000000101 0000000000010100 20
...

In the above this is pretty useless, since shifting by 0 bits
doesn't alter the number. In fact, IIRC, it has undefined behaviour
(are you sure it didn't read
#define PHONG_RV (1<<0)
#define PHONG_NH (1<<1)

that would make far more sense)
 
A

Alexis Gatt

Thanks for the answer.

<< appplied to integers is know as the 'bitshift left' operator

I know that. i just dont understand why someone would define flags in
this way rather than the good old "#define MY_FLAG 0x00001"
(are you sure it didn't read
#define PHONG_RV (1<<0)
#define PHONG_NH (1<<1)

that would make far more sense)

The whole list of flags is actually

#define PHONG_RV (0<<0)
#define PHONG_NH (1<<0)
#define PHONG_ORIG (0<<1)
#define PHONG_NEW (1<<1)
#define PHONG_PHONG (0<<2)
#define PHONG_SCHLICK (1<<2)
 
K

Karl Heinz Buchegger

Alexis said:
Thanks for the answer.



I know that. i just dont understand why someone would define flags in
this way rather than the good old "#define MY_FLAG 0x00001"

So why then are you asking:
Could someone please explain me how they work please?


The whole list of flags is actually

#define PHONG_RV (0<<0)
#define PHONG_NH (1<<0)
#define PHONG_ORIG (0<<1)
#define PHONG_NEW (1<<1)
#define PHONG_PHONG (0<<2)
#define PHONG_SCHLICK (1<<2)

The idea behind all this seems to be:

The value PHONG_RV is enocded, if bit 0 has the value 0, hence 0 << 0
The value PHONG_NH is encoded, if bit 0 has the value 1, hence 1 << 0
The value PHONG_ORIG is encoded, if bit 1 has the value 0, hence 0 << 1
PHONG_NEW 1 1 1 << 1
PHONG_PHONG 2 0 0 << 2
PHONG_SCHLICK 2 1 1 << 2

thus the individual values can simply be order together to get the
correct result.

Well. It is a great idea for documentation. But then, not that usefull for
actual programming. I would not introduce 2 macros for the same bit and name
them differently but instead just have one. Much less confusion in the long run.
Especially because the 0-coding macros cannot easily be used for generating masks.
If you want to test if a flags variable contains the value PHONG_ORIG, there is no way
to express that using PHONG_ORIG. Instead one has to use PHONG_NEW and must have the
knowledge that PHONG_ORIG is the conceptual complement of PHONG_NEW.

so instead of
if( (Flags & PHONG_ORIG) == PHONG_ORIG )

one has to write
if( ( Flags & PHONG_NEW ) != PHONG_NEW )
or
if( !(Flags & PHONG_NEW ) )

to express that idea.
 
C

Chris Theis

[SNIP]
Well. It is a great idea for documentation. But then, not that usefull for
actual programming. I would not introduce 2 macros for the same bit and
name
them differently but instead just have one. Much less confusion in the
long run.
Especially because the 0-coding macros cannot easily be used for
generating masks.
If you want to test if a flags variable contains the value PHONG_ORIG,
there is no way
to express that using PHONG_ORIG. Instead one has to use PHONG_NEW and
must have the
knowledge that PHONG_ORIG is the conceptual complement of PHONG_NEW.

so instead of
if( (Flags & PHONG_ORIG) == PHONG_ORIG )

one has to write
if( ( Flags & PHONG_NEW ) != PHONG_NEW )
or
if( !(Flags & PHONG_NEW ) )

to express that idea.


Yikes, somehow that idea/concept scares me ;-)

Chris
 
G

Greg

Alexis said:
Hi guys,

I was reading the source code of a lib, and I came across this odd way
of defining flags

#define PHONG_RV (0<<0)
#define PHONG_NH (1<<0)

Here is how they're used:

##### START CODE #####

BRDF *Phong_BRDF::Create_Phonglike(const char *params,
int Phong_Flags=PHONG_PHONG)
{
// some code

if (strcasecmp(flag1,"rv") == 0)
Phong_Flags |= PHONG_RV;

##### END CODE #####


Could someone please explain me how they work please?

Many thanks

Alexis

The code doesn't work very well. Using a zero to store a distinct value
is error-prone to say the least. In fact I would have expected the
compiler to warn about this line:

Phong_Flags |= PHONG_RV;

since it has no side effects (in other words, it does nothing). And if
theprogrammer is going to use macros, at least make them function
macros:

#define PHONG_RV(a) (!(0x01 & a))

After all, you don't have a PHONG_RV unless you a set of flags. Of
course the C++, more typesafe version would be an inline function:

inline bool PHONG_RV(unsigned int inFlags)
{
return not (0x01 bitand inFlags);
}

Greg
 

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,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top