[comp.lang.c] Bit Masking Question

angst@cs.ucsb.edu (Hopelessly in love w/Donna Reed) (06/23/91)

This is not necessarily a C question, but since I'm programming it C,
I can ask in that context.

What I'm doing is reading characters from a file and I'd like to 
categorise the characters into 3 groups based on their 2 most-
significant bits.  Group 1 has '11' in their MSb's, group 2 has
'10' in their MSb's, and group 3 has '0X' (X = don't care) in
their MSb's.

Here's how I'm currently doing it:

    #define FMASK   0xC0
    #define RMASK   0x80

    int c;
    ...
	    switch (c & FMASK) {
		case FMASK:
		    Do stuff for group 1
		    ...

		case REPMASK:
		    Do stuff for group 2
		    ...
	    
		case 0x0:
		case 0x40:
		    Do stuff for group 3
		    ...

		default:
		    fprintf (stderr, "bad news!\n");
	    }

This seems to work, but I'd like comments.  Is there a better way to
do this?  Should I make #define's for 0x0 and 0x40?  Is there a way
to #define bits?o

Thanks in advance for any help!

"Let the fools have their tartar sauce."	|          Dave Stein
  		        - Mr. Burns		|       angst@cs.ucsb.edu
						|    angst%cs@ucsbuxa.bitnet

bhoughto@pima.intel.com (Blair P. Houghton) (06/24/91)

In article <12191@hub.ucsb.edu> angst@cs.ucsb.edu (Hopelessly in love w/Donna Reed) writes:

Yeah, she's a babe, alright.  A member of a dying breed.
Unless you count that such competence has moved into the
cubicles next to me with rather heartening frequency.

>What I'm doing is reading characters from a file and I'd like to 
>categorise the characters into 3 groups based on their 2 most-
>significant bits.  Group 1 has '11' in their MSb's, group 2 has
>'10' in their MSb's, and group 3 has '0X' (X = don't care) in
>their MSb's.

The only other (sensible, non-shifting) way to do it is

	if ( c & 0x80 )
	    if ( c & 0x40 )
		/* ops for Group 1 */
	    else
		/* ops for Group 2 */
	else
	    /* ops for Group 3 */

But this uses more than one `&' operation, which may as much
as double the decision time (although the optimizer may just
surprise you).

I prefer your way.  However, you seem to believe that the
two significant bits can be something other than `11',
`10', `01', and `00' (note the impossible-to-reach
printf()).  That is, after the cases for FMASK and REPMASK,
you should have only the default as the case for Group 3
(although the optimizer may just surprise me).

				--Blair
				  "*i = i[0];"

jos@and.nl (J. Horsmeier) (06/24/91)

In article <12191@hub.ucsb.edu> angst@cs.ucsb.edu (Hopelessly in love w/Donna Reed) writes:
>What I'm doing is reading characters from a file and I'd like to 
>categorise the characters into 3 groups based on their 2 most-
[...]
>
>    #define FMASK   0xC0
>    #define RMASK   0x80
>    int c;
>	    switch (c & FMASK) {
[ normal cases ...]
>		case 0x0:
>		case 0x40:
>		    Do stuff for group 3

		^^^^^^ Make this the default ...
>		    ...
>
>		default:
>		    fprintf (stderr, "bad news!\n");

		^^^^^^ this is the same kind of paranoia as:

		for (i= 0; i < 10; i++)
		   if (i >= 10) ZombyWoof();
>	    }
>
>This seems to work, but I'd like comments.  Is there a better way to
>do this?  Should I make #define's for 0x0 and 0x40?  Is there a way
>to #define bits?o

This is not really much of a problem is it? Your code works fine, 
it's compact, fast etc. It'll do the job :-)


Jos


+----------------------------------------------------------------------+
|O   J.A. Horsmeier AND Software B.V.        phone : +31 10 4367100   O|
|O                  Westersingel 106/108     fax   : +31 10 4367110   O|
|O                  3015 LD  Rotterdam NL    e-mail: jos@and.nl       O|
|O--------------------------------------------------------------------O|
|O               I am a Hamburger (F. Zappa 1974)                     O|
+----------------------------------------------------------------------+

Joe_W_Wright@cup.portal.com (06/25/91)

All characters will fit your three stated cases, therefore the printf()
is not even reachable.  Try this.

#define RMASK 0xc0
#define FMASK 0x80

	switch (c & RMASK) {
		case RMASK : do1(); break;
		case FMASK : do2(); break;
		default    : do3();
	}

Should work everywhere.
Joe Wright