# Flags

Discussion in 'C++' started by Alexis Gatt, Aug 25, 2005.

1. ### Alexis GattGuest

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 #####

Many thanks

Alexis

Alexis Gatt, Aug 25, 2005

2. ### Guest

#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

, Aug 25, 2005

3. ### Karl Heinz BucheggerGuest

Alexis Gatt wrote:
>
> 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 #####
>
>

<< 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)

--
Karl Heinz Buchegger

Karl Heinz Buchegger, Aug 25, 2005
4. ### Alexis GattGuest

On 2005-08-25 13:01:30 +0100, Karl Heinz Buchegger <> said:
> << 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)

Alexis Gatt, Aug 25, 2005
5. ### Karl Heinz BucheggerGuest

Alexis Gatt wrote:
>
>
> On 2005-08-25 13:01:30 +0100, Karl Heinz Buchegger <> said:
> > << 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"

So why then are you asking:

>
> > (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)

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.

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.

--
Karl Heinz Buchegger

Karl Heinz Buchegger, Aug 25, 2005
6. ### Chris TheisGuest

"Karl Heinz Buchegger" <> wrote in message
news:...
[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
> 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.
>
> 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

Chris Theis, Aug 25, 2005
7. ### GregGuest

Alexis Gatt wrote:
> 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 #####
>
>
>
> 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

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

Greg, Aug 25, 2005