From: mouse@thunder.mcrcim.mcgill.edu (der Mouse)
Newsgroups: comp.lang.c
Subject: Re: a question about if and case
Date: 16 Dec 92 09:39:19 GMT
Organization: McGill Research Centre for Intelligent Machines

In article <1gi6poINN3lv@nz12.rz.uni-karlsruhe.de>, "hans friedrich steffani" <GM08@DKAUNI2.BITNET> writes:

[compressed -dM]
> if( i == 1 || i == 25 || i == 125 )
>  { /* do something sophisticated */ }
> if( i == 2 || i == 30 || i == 244 )
>  { /* do something different */ }

> or should i use

> switch( i )
> { case 1: case 25: case 125:
>      /* do something sophisticated */
>      break;
>   case 2: case 30: case 244:
>      /* do something different */
>      break;
>   default:
>      break
>  }

> or is there a third way??

Sure there is.

void do_something_sophisticated(void);
void do_something_different(void);
static void (*table[])(void) = {
	0,						/* 0 */
	do_something_sophisticated,			/* 1 */
	do_something_different,				/* 2 */
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* 3..24 */
	do_something_sophisticated,			/* 25 */
	0,0,0,0,					/* 26..29 */
	do_something_different,				/* 30 */
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* 31..50 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* 51..75 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* 76..100 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* 101..124 */
	do_something_sophisticated,			/* 125 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* 126..150 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* 151..175 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* 176..200 */
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,	/* 201..225 */
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,		/* 226..243 */
	do_something_different,				/* 244 */
	};
#define TABLESIZE (sizeof(table)/sizeof(table[0]))
...
	void (*f)(void);
...
	if ((i >= 0) && (i < TABLESIZE) && table[i]) (*table[i])();

A table like this would normally be used only for a somewhat less
sparse situation; entries 1, 2, 25, 30, 125, and 244 would usually be a
situation for a switch().  I assume that the values are somewhat less
random in the real code.  (If you do use cascaded ifs or a switch, I
strongly urge that the magic constants be replaced by #defines whose
names are chosen to describe their meanings.  Magic numbers are usually
a Bad Thing.)

The only reasons for using cascaded ifs instead of a switch are (a) you
can't use a switch for some language reason (eg, the comparisons are
more complicated than simple integer equality) or (b) you have to
kludge around a broken compiler.  Any compiler that generates worse
code for the switch than for the cascade of ifs should cause you to
generate a bug report, and if possible avoid using that compiler.
There really is no excuse for it; a cascade of ifs is one of the basic
ways of implementing a switch, and when the switch is very sparse, it
can be the only practical way.  (Device-driver ioctl switches often do
this, because they are often very sparse, with six or seven cases
present from a range of a billion or so.)

					der Mouse

			    mouse@larry.mcrcim.mcgill.edu
Xref: sparky comp.lang.c:18716 comp.lang.c++:18261 comp.lang.pascal:7591