• Advertisement
Sign in to follow this  

flag and variable, or variable w/ reserved value?

This topic is 863 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

flag and variable, or variable w/ reserved value?

 

which is better?

 

all the time, i come across the "pattern" of a variable storing a value, and a boolean or reserved value saying whether its in effect or not.

 

or a boolean or reserved value indicating "none" or "N/A" or "don't care".

 

 

an example using a reserved value:      

current_weapontype_ID_number    // an object_type ID number, or -1 for none.

 

an example using a variable and a boolean:        

dropped_object[n].data[0]   // generic var. for travois: 0=not carried, 1=carried.

dropped_object[n].data[1]   // generic var. for travois: ID number of player carrying the travois

 

other than the obvious fact that a flag requires a second variable, are there any advantages one way or the other?

 

i run into this "pattern" a lot, and use both methods. but i would like to establish a coding policy one way or the other.

 

Share this post


Link to post
Share on other sites
Advertisement

I would default to using a well-defined sentinel value for this (use a named constant, e.g. const int InvalidObjectId = -1). Managing a single value is always easier than managing two that need to be kept in sync.

 

The exception would be if you absolutely require the full range of values that the variable provides.

 

I guess you could also use a struct that has both the id and the "is valid" flag, and class invariants to ensure the state is consistent.

Edited by phil_t

Share this post


Link to post
Share on other sites

It depends on the situation.

 

Sometimes a key value or sentinel case is better.  It may be easier, it may be faster, it may be less work to maintain.

 

Other times a separate flag is better. It may be easier, it may be faster, it may be less work to maintain.

 

 

The case of NULL is interesting because it follows both.  The ability to have a "not a value" value is great in some contexts. However, the constant check against null has a serious cost.  

 

In many situations in games it is better to not test against NULL at all, always pointing values to a valid placeholder. It still serves as a sentinel value of sorts, but using it is not catastrophic. Anything using the placeholder gets flagged, and in final builds the placeholder is replaced with an invisible object. Following a pointer to a placeholder is valid, following the null pointer is really bad.

 

Other times it can be good to have an external flag. If the cost of checking against an empty flag, or a dirty flag, or some other marker is expensive then having a separate flag can be a great solution. Especially in polymorphic situations, the cost of checking against a known base-class flag is small relative to the cost of virtual dispatch. Of course it is better if you can avoid the tests fully, but if you have options between a fast flag and a slower process, the fast flag is a good thing.

 

It is all up to context.

Share this post


Link to post
Share on other sites


I would default to using a well-defined sentinel value for this (use a named constant, e.g. const int InvalidObjectId = -1). 

 

that sounds like one vote for reserved values.

 


Managing a single value is always easier than managing two that need to be kept in sync.

 

a good point.

 


The exception would be if you absolutely require the full range of values that the variable provides.

 

seldom the case.  variables are often array indices, stored in ints, which leaves negative numbers free for use as reserved values, similar to a function that returns a non-negative value on success, or a reserved negative value as an error code.

 


I guess you could also use a struct that has both the id and the "is valid" flag, and class invariants to ensure the state is consistent.

 

that _would_ be more bullet proof that relying on coder discipline to keep them in sync.   "kid safe" code isn't really a concern here though.  guess i'm looking more for efficiency - less code entry, simpler algos, that kind of stuff. right now, its seems to be a rather even trade off between the extra code and comments for a flag vs a reserved value.

 

 

 

Share this post


Link to post
Share on other sites


The case of NULL is interesting because it follows both.  The ability to have a "not a value" value is great in some contexts. However, the constant check against null has a serious cost.  
 
In many situations in games it is better to not test against NULL at all, always pointing values to a valid placeholder. It still serves as a sentinel value of sorts, but using it is not catastrophic. Anything using the placeholder gets flagged, and in final builds the placeholder is replaced with an invisible object. Following a pointer to a placeholder is valid, following the null pointer is really bad.

 

fortunately, i don't have to deal with such issues. i use statically allocated arrays in the data segment, combined with code designed to prevent the need for range checks (to the maximum extent possible).  for the stuff i'm making its "good enuf" to "geter dun".

 


Other times it can be good to have an external flag. If the cost of checking against an empty flag, or a dirty flag, or some other marker is expensive then having a separate flag can be a great solution. Especially in polymorphic situations, the cost of checking against a known base-class flag is small relative to the cost of virtual dispatch. Of course it is better if you can avoid the tests fully, but if you have options between a fast flag and a slower process, the fast flag is a good thing.

 

a valid consideration. again, i'm lucky in that i don't have to deal with such things. i'm pretty much PODs and procedural code, organized into ADTs.  i'm talking about simple cases, where the difference between checking a flag and a reserved value is negligible.

Share this post


Link to post
Share on other sites

I always try to reduce the number of variables, so if possible, I fold the "not a value" value into the variables I must have anyway, using a named constant to indicate the absence of a value (sometimes there are even several such values).

 

The exceptions are the cases where you don't have room, eg a 16bit unsigned value where all 65536 values are valid.

 

 

Edit: Perhaps this is more an issue in return values of functions, where you don't have space to easily add a second value? (at least in some of the languages).

Edited by Alberth

Share this post


Link to post
Share on other sites


Of course, there is a Boost library for it

 

seems like there's a boost library for everything these days! <g>

 

if i can do something trivial like this in-house as fast as i can with a lib, i'll always go in-house.    

 

cobbling a game together with as many 3rd party libs vs in-house code as possible always struck me as a rather house-of-cards way to build things. don't get me wrong, i'm a formally trained engineer, and understand the value of systems engineering from off-the-shelf components, i guess its just that i've seen so many games get it wrong. then again, i guess if they can't write the lib themselves, what should i expect? them that can, do. them that can't, teach, them that can't teach, administrate - that kind of concept.

Share this post


Link to post
Share on other sites


I always try to reduce the number of variables, so if possible, I fold the "not a value" value into the variables I must have anyway, using a named constant to indicate the absence of a value (sometimes there are even several such values).

 

that would be two votes favoring reserved value when possible.

 

i tend to use reserved value myself. its the natural solution that first comes to mind (at least for me).

 

in my second example above, in that case, i already had a generic int data[5] array ready for use in an object struct, so i used the first var as the flag, and the second as the value.

 


The exceptions are the cases where you don't have room, eg a 16bit unsigned value where all 65536 values are valid.

 

yes. it sounds like for simple cases, here a flag is called for, and in all other cases, reserved values will suffice.    perhaps that should be the coding policy. obviously this would not include cases where checking one vs the other is non-trivial (as mentioned by frob).

 


Edit: Perhaps this is more an issue in return values of functions, where you don't have space to easily add a second value? (at least in some of the languages).

 

i was just adding a routine to return the index of a travois world object carried by player N, or negative 1 for none.  and i noticed that travois objects use data[0] as a flag, and data[1] as the value. and this question of whether flag or reserved value is better has been bugging me now for a few weeks. one of those things that just occurs to you that you never really gave much thought to before on a "company wide coding policy" basis.  thus my OP.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement