[net.lang.c] How does one construct a mask for the MS bit?

ken@turtlevax.UUCP (Ken Turkowski) (02/28/85)

The VAX and PDP-11 have the property that
	int x;
	x = 12000;
	write(df, &x, 2);
gives the same results whether an int is short or long.
On the 68000, this gives different results.

This could be interpreted as follows:  truncation of bytes or words for
the DEC computers are appropriate for integers, whereas truncation for
the 68000 is appropriate for fractions.  Taking the "first" digit of
12345 yields 5 for DEC, and 1 for Motorola.

I would like to be able to have the write sequence above give the same
results for the 68000, regardless of whether the int is long or short.

This would require the generation of a mask for the most significant
bit of an int, where the int could be any arbitrary size.  Does the
following not work on any machine?

main() {
	int x;
	x = (-1) & ~((unsigned)(-1) >> 1);
	printf("%x\n", x);
}

Then I could sequence through bits as follows:

for (i = 0; i < N; i++)
	if (joe & (ms >> i))
		printf("Bit %d of joe is set\n", i);

-- 

Ken Turkowski @ CADLINC, Menlo Park, CA
UUCP: {amd,decwrl,nsc,seismo,spar}!turtlevax!ken
ARPA: turtlevax!ken@DECWRL.ARPA

cottrell@NBS-VMS.ARPA (03/02/85)

/*
> This would require generation of a mask for the most significant bit

int msbit()
{	register int msb = 1;
	while ((msb <<= 1) > 0);
	return(msb);
}

I am assuming that the msb is used as the sign bit. If that's not 
portable, then shift until msb is zero, counting the shifts. Then
return(1 << --count). (I am also assuming an int is more than one bit :-)

	jim
*/

ptw@encore.UUCP (P. Tucker Withington) (03/04/85)

>> This would require generation of a mask for the most significant bit

It should be easy to make a constant that masks a machine's "high" bit, but
as I mentioned a while back, ~(~(unsigned)0>>1) croaks pcc in a static
declaration; apparently because it does not know how to simplify casts in a
constant.  (It works fine as auto or in an expression, but then you're doing
unnecessary work at run time, especially if you made it a #define.)

The only feedback I got was that you "should" be allowed to have casts in a
constant; that they were "accidentally" left out of K&R...

                               o.o      --tucker
                                ~

bass@dmsd.UUCP (John Bass) (03/08/85)

seems that this should work:

#define MSB(a)		(1<<((sizeof a) * 8 - 1))

for most unix machines.
-- 
John Bass
DMS Design (System Performance and Arch Consultants)
{dual,fortune,idi,hpda}!dmsd!bass     (408) 996-0557

MLY.G.SHADES%MIT-OZ@MIT-MC.ARPA (03/08/85)

	~(~(unsigned)0>>1) is not portable either i believe.  as i
remember in k&r the >> operator can, and in some compilers does, allow
sign propagation.  this is nominally a bug in the interpretation of
unsigned arithmetic but that is the way of life here in the big city.

	i can't think of any way to guarantee a compiler time,
compiler generated, constant for the most significant bit that is
going to work on some of the more brain-damaged c compiler's around.

                      shades%mit-oz@mit-mc.arpa

stew@harvard.ARPA (Stew Rubenstein) (03/10/85)

> seems that this should work:
> 
> #define MSB(a)		(1<<((sizeof a) * 8 - 1))
> 
> for most unix machines.
> -- 
> John Bass
> DMS Design (System Performance and Arch Consultants)
> {dual,fortune,idi,hpda}!dmsd!bass     (408) 996-0557

Is it portable to assume 8 bit bytes?  Answer:  no, but since there is no
bitsizeof operator, sometimes we must.  There are unix machines which do
not use 8 bit bytes (the BBN C-30 and C-70 come to mind, maybe also some
honeywell machines).  There is also the PDP-10 which, to the best of my
knowledge, does not run unix, but does have C.
-- 
-----------------------
Stew Rubenstein     UUCP: ihnp4!harvard!stew
Harvard Chemistry   ARPA: stew@harvard

dae@psuvax1.UUCP (Daemon) (03/11/85)

The below is at least a stab in the right direction;
our cpp is the "old" 4.2 one--the one without the -M
option.
-----------------------cut here for msb.c------------------------------
#define msb(x) (1 << (8 * sizeof(x)) - 1)

main()
{
	int i = msb(int);
	short s = msb(short);
	char c = msb(char);

	printf("Int:  %d\n", i);
	printf("Short:  %d\n", s);
	printf("Char:  %d\n", c);
}
--------------------------end msb.c-----------------------------------
-- 
 \ / \/ From the furnace of Daemon ( ...{psuvax1,gondor,shire}!dae )
  \  / +1 814 237 1901 "I will have no covenants but proximities"  [Emerson]
   \/
                         Don't get mad.  Get even.

mab@druxp.UUCP (BlandMA) (03/12/85)

John Bass in article <169@dmsd.UUCP> recommends:
>	#define MSB(a)		(1<<((sizeof a) * 8 - 1))

Stew Rubenstein in article <455@harvard.ARPA> replies:
>	Is it portable to assume 8 bit bytes?  Answer:  no....

If you're running UNIX System V (and possibly other UNIX systems, I don't
know), take a look at /usr/include/values.h, which defines a number of
constants that might be of use, such as:

	BITSPERBYTE  number of bits in a byte
	HIBITS       bit mask for the high bit of a short
	HIBITI       ditto for int
	HIBITL       ditto for long
	MAXSHORT     maximum value of a signed short
	MAXINT       ditto for int
	MAXLONG      ditto for long

HIBITS, HIBITI, and HIBITL are macros defined in terms of BITSPERBYTE
using the same formula that John Bass gave.  BITSPERBYTE is conditionally
compiled using #if.

UNIX is a trademark of AT&T Bell Laboratories.
-- 
Alan Bland
{ihnp4, allegra}!druxp!mab
AT&T Information Systems Labs, Denver

dave@inset.UUCP (Dave Lukes) (03/20/85)

Newsgroups: net.lang.c
Subject: Re: How does one construct a mask for the MS bit?
References: <8849@brl-tgr.ARPA>, <169@dmsd.UUCP>

> seems that this should work:
> 
> #define MSB(a)		(1<<((sizeof a) * 8 - 1))
> 
> for most un*x machines.
> -- 
> John Bass

MOST UN*X machines?? Go suck a Honeywell !! (or A BBN)
====
``Well, it works on all the machines I use''
is a great attitude if you can afford it: not everyone can (or wants to!).

Even if you are willing to have your code break on a machine with one more
bit, at least COMMENT the fact beforehand.
	      =======

Also, if the the byte/word/long ... size is so important:


		WORK   IT   OUT !!!!!!!!!!
		==========================

How's this:

	bitsperword() {

		unsigned int i = ~0;
		int nbits = 0;

		do
			nbits++;
		while((i >>= 1) != 0);
		return nbits;
	}

		Yours portably,
			Dave Lukes