[comp.lang.c] IsUnsigned

jhsu@Neon.Stanford.EDU (Jeffrey H. Hsu) (07/17/90)

Fellow C hackers,

	Here is a C question I was asked at a Microsoft interview (no, I didn't
get the job...).

	How would you write a space efficient algorithm/function in C that 
takes in an integer and returns 0 if signed and 1 if unsigned?

	IsUnsigned(a)
		int a;
	{
	}

I would appreciate answers from anyone.

Thanks,
Jeff

diamond@tkou02.enet.dec.com (diamond@tkovoa) (07/17/90)

In article <1990Jul16.214155.5087@Neon.Stanford.EDU> jhsu@Neon.Stanford.EDU (Jeffrey H. Hsu) writes:

>	Here is a C question I was asked at a ________t interview
>	How would you write a space efficient algorithm/function in C that 
>takes in an integer and returns 0 if signed and 1 if unsigned?
>	IsUnsigned(a)
>		int a;
>	{
>	}

Uh, maybe
    /* Remember first to #define signed or #define unsigned. */
    IsUnsigned(a)
    #ifdef signed
            int a;
    #else
            unsigned a;
    #endif
    {
    #ifdef signed
            return 0;
    #else
            return 1;
    #end
    }
Doesn't sound like a job that a programmer would want.....
-- 
Norman Diamond, Nihon DEC     diamond@tkou02.enet.dec.com
This is me speaking.  If you want to hear the company speak, you need DECtalk.

darcy@druid.uucp (D'Arcy J.M. Cain) (07/18/90)

In article <1990Jul16.214155.5087@Neon.Stanford.EDU>
jhsu@Neon.Stanford.EDU (Jeffrey H. Hsu) writes:
>	Here is a C question I was asked at a Microsoft interview (no, I didn't
>get the job...).
>	How would you write a space efficient algorithm/function in C that 
>takes in an integer and returns 0 if signed and 1 if unsigned?
>	IsUnsigned(a)
>		int a;
>	{
>	}
How about:
#define IsUnsigned(a) 0

Since your declaration says that a is an int then you are saying it
is always signed.

-- 
D'Arcy J.M. Cain (darcy@druid)     |   Government:
D'Arcy Cain Consulting             |   Organized crime with an attitude
West Hill, Ontario, Canada         |
(416) 281-6094                     |

karl@haddock.ima.isc.com (Karl Heuer) (07/19/90)

In article <1990Jul16.214155.5087@Neon.Stanford.EDU> jhsu@Neon.Stanford.EDU (Jeffrey H. Hsu) writes:
>How would you write a space efficient algorithm/function in C that
>takes in an integer and returns 0 if signed and 1 if unsigned?

Define your terms.  Is this to be a function or a macro?  If a function, then
its argument must have a type known at compile-time: what type is it?  Is the
goal to determine the signedness of the type of the argument, or the value?

A non-trivial specification is to write a macro to find the signedness of the
(promoted) type of its argument expression.  One way to do this is
	#define IsUnsigned(x) (((x)*0-2)/2+1 != 0)

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

jak@sactoh0.UUCP (Jay A. Konigsberg) (07/19/90)

In article <1990Jul16.214155.5087@Neon.Stanford.EDU> jhsu@Neon.Stanford.EDU (Jeffrey H. Hsu) writes:
>
>	How would you write a space efficient algorithm/function in C that 
>takes in an integer and returns 0 if signed and 1 if unsigned?
>

I would bet that they had something like this in mind.

--------------------------------------------------------------------------
#define MASK 10000000
#define TRUE 1
#define FALSE 0

main()
{
signed(1)  ? printf("unsigned\n") : printf("signed\n");
signed(-1) ? printf("unsigned\n") : printf("signed\n");
}

signed(number)
long number;
{
if( number & MASK )
    return(FALSE);
else
    return(TRUE);
}
-- 
-------------------------------------------------------------
Jay @ SAC-UNIX, Sacramento, Ca.   UUCP=...pacbell!sactoh0!jak
If something is worth doing, its worth doing correctly.

macphee@convex.COM (Scott C. Mac Phee) (07/19/90)

I would think what we are really looking for is :

 o Assume (always) that the type we are checking is of type int.

int
IsUnsigned(x)
unsigned x ;
{
	return(x&(1<<(sizeof(int)-1))) ;
}

Scott

Convex Computer Corporation
...uunet!convex!macphee
(214) 497-4772

karl@haddock.ima.isc.com (Karl Heuer) (07/20/90)

In article <3539@sactoh0.UUCP> jak@sactoh0.UUCP (Jay A. Konigsberg) writes:
>I would bet that they had something like this in mind.
>	#define MASK 10000000
>	signed(number) long number; {
>	    if(number & MASK) return(FALSE); else return(TRUE);
>	}

If that's what they had in mind, then `return (number >= 0)' is a trivial
solution-- which doesn't depend on the unspecified internal representation of
negative numbers, the number of bits in a long int, or remembering to specify
the correct radix for the bitmask.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

netnews@mtunh.ATT.COM (netnews dptg) (07/20/90)

How about this:

	IsUnsigned (a) 
	int a;
	{
		return( !(a >> ((sizeof(int)*8)-1)));
	}

The only real assumption that this function makes is that
there are 8 bits in a byte (a fair assumption I think).

If you don't care about portability (I do, though) and like to make
more assumptions (like the size of the int on your system)
you can make it even shorter:

4 byte int:

	IsUnsigned (a) 
	int a;
	{
		return( !(a >> 31));
	}

2 byte int:

	IsUnsigned (a) 
	int a;
	{
		return( !(a >> 15));
	}

BTW: What you have experienced says much more about Microsoft than
     about yourself. Don't let it eat you.

Ralph Hayon
AT&T Bell Laboratories, 
Middletown, NJ

njk@diku.dk (Niels J|rgen Kruse) (07/20/90)

karl@haddock.ima.isc.com (Karl Heuer) writes:
>In article <3539@sactoh0.UUCP> jak@sactoh0.UUCP (Jay A. Konigsberg) writes:
>>I would bet that they had something like this in mind.
>>      #define MASK 10000000
>>      signed(number) long number; {
>>          if(number & MASK) return(FALSE); else return(TRUE);
>>      }
>If that's what they had in mind, then `return (number >= 0)' is a trivial
>solution-- which doesn't depend on the unspecified internal representation of
>negative numbers, the number of bits in a long int, or remembering to specify
>the correct radix for the bitmask.

Not to mension giving an integer argument to a function
expecting long without prototype in scope and implementing the
reverse operation of the one wanted (if it hadn't been for the
missing 0x of course).

Considering *********'s reputation for buggy code, they just
_might_ have liked it.  :-) ;-)

If squeezing codesize is the big issue, something like this
might be better:

IsUnsigned (int number) {
  return ~(unsigned)number / ((unsigned)-1/2 + 1);
}

This will compile to 2 instructions on most machines with
decent compilers (ignoring calling sequence stuff).  Gcc on a
Vax compiles it to:

#NO_APP
gcc_compiled.:
.text
        .align 1
.globl _IsUnsigned
_IsUnsigned:
        .word 0x0
        mcoml 4(ap),r0
        extzv $31,$1,r0,r0
        ret

But it really is a silly question.  I would have been baffled
too.  Why would anybody ever want to write such a silly
function?  It is like those riddles, where you know that no
matter what you answer, you misunderstood the question.
-- 
Niels J|rgen Kruse 	DIKU Graduate 	njk@diku.dk

pmk@craycos.com (Peter Klausler) (07/21/90)

macphee@convex.COM proposes:
> int
> IsUnsigned(x)
> unsigned x ;
> {
> 	return(x&(1<<(sizeof(int)-1))) ;
> }

From this code I can conclude that Convex uses a 1-bit character set and that
a sign bit of 1 indicates a positive value, not a negative one. Amazing what's
being done in hardware these days, no?

steve@groucho.ucar.edu (Steve Emmerson) (07/22/90)

I would have answered that they (the company) should have a very good
reason not to fire the question's author (e.g. they did it deliberately,
with malice aforethougt and not from stupidity).

Steve Emmerson        steve@unidata.ucar.edu        ...!ncar!unidata!steve

cwebb@cbnewsk.att.com (charles.a.webb) (07/22/90)

jhsu@Neon.Stanford.EDU (Jeffrey H. Hsu) writes:
>	Here is a C question I was asked at a Microsoft interview (no, I didn't
>get the job...).
>	How would you write a space efficient algorithm/function in C that 
>takes in an integer and returns 0 if signed and 1 if unsigned?
>	IsUnsigned(a)
>		int a;
>	{
>	}


    Do you really want to test if the int is signed vs unsigned, or
positive or negative???  Karl gave an answer to the first question,
and indicated that the second question was "trivial."

>A non-trivial specification is to write a macro to find the signedness of the
>(promoted) type of its argument expression.  One way to do this is
>	#define IsUnsigned(x) (((x)*0-2)/2+1 != 0)
>
>Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

The answer to the pos vs neg value interpretation of the 
question can be trivial, but the trivial answer is likely
to cause the compiler to generate a compare and branch instruction.
If the branches are relatively costly on the machine in question, 
then perhaps a right shift and xor would be faster.

Thus

#define IsUnsigned(x)  ((((unsigned)(x))>>31)^1)

I would be willing to bet that there are some machines 
that can do this in two instructions - the shift and
the xor..... This should be faster and more space efficient
on those machines. Note, however, this is highly non-portable,
and depends on the sizeof int. a *really* smart compiler 
should be able to this type of thing automagically,
but in my (limited) experience, some compilers can be pretty myopic.
If you know all the gory details about the timings of the
assembler instructions generated for the particular machine, then
you can decide which implementation is most efficient. However,
I suspect that in most cases the shift and xor will be faster
and more space efficient. (I have assumed a macro since it
is silly to use a function call here, especially if the objective
is speed!)

I have to admit that I'd never have gotten the answer given
by Karl (I'm no walking lint :-) However, I might question
why you would need such a beast; if the code requires an
unsigned int, then specify an unsigned int. IMHO, you
should know the type of the expression at compile time, and
not have to do this stuff (i.e. don't rely on the default signedness of
an int, short or char - if it is important, explicitly declare it
or use a cast.)

Just some random thoughts. I'd be interested in other opinions. (email)

Chip Webb
AT&T Bell Labs
cwebb@pixels.att.com
att!pixels!cwebb

(Standard disclaimers apply)

jak@sactoh0.UUCP (Jay A. Konigsberg) (07/22/90)

In article <1990Jul20.144241.2560@diku.dk> njk@diku.dk (Niels J|rgen Kruse) writes:
>karl@haddock.ima.isc.com (Karl Heuer) writes:
>>In article <3539@sactoh0.UUCP> jak@sactoh0.UUCP (Jay A. Konigsberg) writes:
>>>I would bet that they had something like this in mind.
>>>      #define MASK 10000000
>>>      signed(number) long number; {
>>>          if(number & MASK) return(FALSE); else return(TRUE);
>>>      }
>>If that's what they had in mind, then `return (number >= 0)' is a trivial
>>solution-- which doesn't depend on the unspecified internal representation of
>
>Not to mension giving an integer argument to a function
>expecting long without prototype in scope and implementing the
>reverse operation of the one wanted (if it hadn't been for the
>missing 0x of course).
>
>Considering *********'s reputation for buggy code, they just
>_might_ have liked it.  :-) ;-)
>
>If squeezing codesize is the big issue, something like this
>might be better:
>
>IsUnsigned (int number) {
>  return ~(unsigned)number / ((unsigned)-1/2 + 1);
>}
>
Well, I'm not the original poster, but I am the one that posted the
solution that did the num & MASK solution. Since I've discussed this
topic with a local systems programmer/manager at a local company and
dicovered that the correct answer is the simple one. Namely:

if ( num < 0 ) return FALSE else return TRUE;

This is both simple and portable. Still I liked the solution of

(num & 1<< (sizeof(int)*8) )

even though it assumes that the sign is stored in the high order bit
(which to my surprise isn't always the case). It will always mask that
high order bit in a rather elegent fassion.

It seems that the original poster left off an important part to the
question. Why did you choose the algrothium you used? The question
is designed to find people who will make things overly complacted
or just don't know very much about how things work - thats where I
got traped. I passed by the simple solution because the question
seemed to imply that it wasn't the best. Oh well, thats why I read
this group.

In fact, the systems programmer liked the question so much, he said
he was going to include it in his interviews in the future.

Well, one good thing has come out of this anyway, I understand more
of how C handles the values it stores and how it relates to the under-
lying hardware. Gee, one down 9,999,999 to go :-)

-- 
-------------------------------------------------------------
Jay @ SAC-UNIX, Sacramento, Ca.   UUCP=...pacbell!sactoh0!jak
If something is worth doing, its worth doing correctly.

mcdonald@aries.scs.uiuc.edu (Doug McDonald) (07/22/90)

In article <2936@mtung.ATT.COM> rdh@mtung.ATT.COM (Ralph Hayon) writes:
>How about this:
>
>	IsUnsigned (a) 

IS what is wanted here a decision as to the **TYPE** of the variable,
signed or unsigned? I assume so. Then I don't see how a function is
possible at all. IT has to have a defined type parameter. Period.

On the other hand a macro should be possible on any given machine.
But can a portable one be written? Portable to any size int (16 bit,
18 bit, 32 bit, 60 bit, 64 bit...), and to ones or twos complement
(sign-magnitude?). This seems like an interesting and useful topic
for comp.lang.c. 

To extend it a bit, how about macros for

is_twos_complement()

is_ones_complement()

word_size(a), which returns the number of bits in a


Doug McDonald

williams@umaxc.weeg.uiowa.edu (Kent Williams) (07/23/90)

What I want to know, is what do they mean by IsUnsigned?

a. Was the number declared to be unsigned? -- No way to test this -- if
it was unsigned, then the sign bit (in most implementation) is just
another bit of significance.

b. Is the number negative? That is the question everyone seems to be
answering, which suggests something trivial like

		int IsUnsigned(int x) { return x >= 0; }

		for which most compilers will generate only two or three instructions.

c. Something else -- who knows?

I noticed a few people couldn't let the chance to do some MicroSoft
bashing.  C'mon -- worry about something important!  They certainly
have no monopoly on stupid interview questions.

Kent Williams                    'Look, I can understand "teenage mutant ninja 
williams@umaxc.weeg.uiowa.edu    turtles", but I can't understand "mutually 
williams@herky.cs.uiowa.edu      recursive inline functions".' - Paul Chisholm

--
Kent Williams                    'Look, I can understand "teenage mutant ninja 
williams@umaxc.weeg.uiowa.edu    turtles", but I can't understand "mutually 
williams@herky.cs.uiowa.edu      recursive inline functions".' - Paul Chisholm

rick@tetrauk.UUCP (Rick Jones) (07/25/90)

I'm suprised that very few people seems to have grasped what the question was
about.  I don't have a copy of the original posting, but as I remember the
question was "how do you write a function or macro to determine if a variable is
unsigned" (or something like that).

The question was not "is the value negative", that is absurdly trivial, it was
to test for the declaration style - maybe to find if an unqualified char is
signed or unsigned, since it can be either.

The red herring in the question is the word "function".  You can't do it with a
function, since the type of a function's formal parameter is defined within the
function, it cannot be passed via the call.  So the first answer is that it has
to be a macro, which will operate on its argument according to the declaration
of that argument.

The essential characteristic of an unsigned value is that it can never be
negative, and the essential characteristic of a signed value is that
complementing its most significant bit will change its sign (assuming 2's
complement representation, which is pretty safe).  Since the other bits are
irrelevant to this test, you can complement them all and get the same result.

Therefore try the following:

#define IsUnsigned(a)	(a >= 0 && ~a >= 0)


It does work - I've tested it.

-- 
Rick Jones					You gotta stand for something
Tetra Ltd.  Maidenhead, Berks			Or you'll fall for anything
rick@tetrauk.uucp (...!ukc!tetrauk.uucp!rick)	     - John Cougar Mellencamp

karl@haddock.ima.isc.com (Karl Heuer) (07/25/90)

In article <15303b1aa0bf26a8c5d4@canremote.uucp> john.russell@canremote.uucp (JOHN RUSSELL) writes:
>[What if the idea was to avoid a branch?]

If the macro is being used in a Boolean context, then you've got a branch
anyway, and simply writing `x >= 0' is optimal.  If it's being used in an
arithmetic context, *and* if `f = (x >= 0)' generates an inefficient branch
that can be avoided by rewriting it in terms of bit-twiddling, *and* if this
difference is critical, then the company should be hiring somebody to fix the
compiler rather than the source code.  And the interviewee should not be
expected to deduce all this from the question as asked!

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

karl@haddock.ima.isc.com (Karl Heuer) (07/25/90)

In article <615@tetrauk> rick@tetrauk.UUCP (Rick Jones) writes:
>I'm suprised that very few people seems to have grasped what the question was
>about.

It's because the question was so poorly worded (as posted; I don't know if it
was asked the same way).  Maybe that was the intent: to see if the interviewee
would give the correct response, "What do you mean?", rather than immediately
starting to write code.

>#define IsUnsigned(a)	(a >= 0 && ~a >= 0)

I think my version is more likely to fold into a compile-time constant.  (I
used `((a)*0-2)/2+1 != 0', which is intended to be fairly robust even against
questionable compilers.)  And why assume 2's-complement if you don't have to?

Trivia question: under what circumstances will Rick's macro produce the wrong
answer to the presumed question?

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

rick@.tetrauk.UUCP (Rick Jones) (07/26/90)

In article <17147@haddock.ima.isc.com> karl@kelp.ima.isc.com (Karl Heuer) writes:
>In article <615@tetrauk> rick@tetrauk.UUCP (Rick Jones) writes:
>>
>>#define IsUnsigned(a)	(a >= 0 && ~a >= 0)
>
>I think my version is more likely to fold into a compile-time constant.  (I
>used `((a)*0-2)/2+1 != 0', which is intended to be fairly robust even against
>questionable compilers.)  And why assume 2's-complement if you don't have to?

I don't disagree.  I just felt something simple and explicit was worth
suggesting since so many people seemed to be going off on weird tangents on
this one.

>Trivia question: under what circumstances will Rick's macro produce the wrong
>answer to the presumed question?

Perhaps I should try to answer that myself!

a.	If signed arithmetic does not use 2's complement notation
b.	For types shorter than int if the compiler's promotion is wrong

Farrell Woods <ftw@westford.ccur.com> mailed me:

> It doesn't work for types where sizeof (type) < sizeof (int).  I
> believe that you can only write a macro which will tell you if the
> *promoted* type is signed or unsigned, as Karl Heuer already pointed out.

The promoted type retains the signedness of the shorter type (that's my
understanding, anyway), and the macro works on all sizes in my test.

A question: if a compiler's promotion causes my macro to fail on short types,
is the compiler broken?  If so, is this macro any use as a compiler test?
Or is my brain broken?
Comments on a postcard please ... (sorry, wrong technology)

-- 
Rick Jones					You gotta stand for something
Tetra Ltd.  Maidenhead, Berks			Or you'll fall for anything
rick@tetrauk.uucp (...!ukc!tetrauk.uucp!rick)	     - John Cougar Mellencamp

karl@haddock.ima.isc.com (Karl Heuer) (07/27/90)

In article <619@.tetrauk.UUCP> rick@tetrauk.UUCP (Rick Jones) writes:
>In <17147@haddock.ima.isc.com> karl@kelp.ima.isc.com (Karl Heuer) writes:
>>>#define IsUnsigned(a)	(a >= 0 && ~a >= 0)
>>
>>Trivia question: under what circumstances will Rick's macro produce the wrong
>>answer to the presumed question?
>
>Perhaps I should try to answer that myself!
>a.	If signed arithmetic does not use 2's complement notation

Actually I had a more specific answer in mind--even on such machines it works
for *most* values.  I think there are only two exceptions:

a1.  The signed value 0 on a one's complement machine
a2.  The signed value INT_MAX on a sign-magnitude machine

In both cases ~a is -0, which is >= 0 despite having the sign bit set.

>b.	For types shorter than int if the compiler's promotion is wrong
>
>The promoted type retains the signedness of the shorter type (that's my
>understanding, anyway)

Nope.  Classic C compilers are divided on the issue, and ANSI C requires
value-preserving rather than unsigned-preserving promotion.  So, if short is
16 bits and int is 32, unsigned short promotes to signed int.

Also: c.  If the argument is an expression whose primary operator with
sufficiently low precedence, e.g. `IsUnsigned(1||1)'.  (Fix: parenthesize the
two instances of `a' in the macro body.)

d.  If the arg is an expression with side effects, e.g. `IsUnsigned(*p++)'
where `int *p' points into `{ 1, ~1 }'.  (Fix: use an algorithm that evaluates
the arg only once.  Not a problem in practice, since the only use for this
macro is in a situation where the side effects would wreak havoc anyway.)

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

will@kfw.COM (Will Crowder) (07/27/90)

I promised myself I wouldn't get into this....

It sounds like the question has to do with whether or not a given
*type* is signed or unsigned for a given implementation.   That 
could be a useful thing to know, and ideally, the result would
be a compile-time constant.  The specific case I'm thinking of
char, which, according to ANSI, can be signed or unsigned as
the implementation desires.

What's wrong with:

#define IsUnsigned(type)	((type)0 - 1 > 0)

Will

steve@groucho.ucar.edu (Steve Emmerson) (07/29/90)

In <1990Jul27.161339.14712@kfw.COM> will@kfw.COM (Will Crowder) writes:

>What's wrong with:

>#define IsUnsigned(type)	((type)0 - 1 > 0)

Unless I'm mistaken, in ANSI C "(char)0" will, on most machines,
promote to "signed int" due to the value-preserving rule; consequently,
the above expression will always be false on those machines, regardless
of the signedness of "char".

Steve Emmerson        steve@unidata.ucar.edu        ...!ncar!unidata!steve

rick@.tetrauk.UUCP (Rick Jones) (07/30/90)

I knew I should have kept out of this!

My suggestion [#define IsUnsigned(a) (a >= 0 && ~a > 0)] will spot a compiler
with wrong promotion of short types, but I have to admit the macro fails with
ANSII promotion, while working with old K&R.  Comes of using pretend ANSII
compilers, I suppose, and K&R version 2 is _horribly_ ambiguous about "~".

Perhaps I finally understand the ANSII promotion rules at last!

-- 
Rick Jones					You gotta stand for something
Tetra Ltd.  Maidenhead, Berks			Or you'll fall for anything
rick@tetrauk.uucp (...!ukc!tetrauk.uucp!rick)	     - John Cougar Mellencamp

will@kfw.COM (Will Crowder) (07/30/90)

In article <8118@ncar.ucar.edu> steve@groucho.ucar.edu (Steve Emmerson) writes:
>In <1990Jul27.161339.14712@kfw.COM> will@kfw.COM (Will Crowder) writes:
>
>>What's wrong with:
>
>>#define IsUnsigned(type)	((type)0 - 1 > 0)
>
>Unless I'm mistaken, in ANSI C "(char)0" will, on most machines,
>promote to "signed int" due to the value-preserving rule; consequently,
>the above expression will always be false on those machines, regardless
>of the signedness of "char".
>
>Steve Emmerson        steve@unidata.ucar.edu        ...!ncar!unidata!steve

You're absolutely right, which Karl Heuer also pointed out to me via
e-mail.

I hate the fact that signedness is not preserved, so I probably blocked
it out of my memory due to severe emotional trauma.  :) :) :)  (In other
words, I blew it.)

I've tried ((type)(-1) > 0) on Turbo C and Gnu CC v1.36, and it seems to
work on both.  It does not, however, work on Sun cc.  A compile-time
switch on Turbo C lets you choose whether you want signed or unsigned
chars, which is handy.

Side note: can anyone out there give a good explanation as to why
chars were *ever* signed in the first place, and why ANSI decided not
to require either signed or unsigned chars (leaving it implementation
dependent)?

Will

karl@haddock.ima.isc.com (Karl Heuer) (07/31/90)

In article <1990Jul30.162449.19240@kfw.COM> will@kfw.com (Will Crowder) writes:
>Side note: can anyone out there give a good explanation as to why
>chars were *ever* signed in the first place,

The pdp11's byte-to-word instruction did sign extension, so it was cheaper to
have chars be signed.  Since ASCII fits in the intersection of signed and
unsigned char, most of the problems were hidden.

>and why ANSI decided not to require either signed or unsigned chars (leaving
>it implementation dependent)?

Because which one is cheaper is an implementation-dependent issue, and, since
most programs don't care (because they don't use char objects as arithmetic
quantities), there was no reason to impose an undue burden on them.

I think the real mistake was in having `char' do triple duty: it's the atomic
text object (for which signedness shouldn't even be an askable question; cf.
Pascal), the allocation quantum (probably should have been spelled `byte'),
and a small integer type (which should be spelled `short short int').

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint

henry@zoo.toronto.edu (Henry Spencer) (08/01/90)

In article <17181@haddock.ima.isc.com> karl@kelp.ima.isc.com (Karl Heuer) writes:
>>Side note: can anyone out there give a good explanation as to why
>>chars were *ever* signed in the first place,
>
>The pdp11's byte-to-word instruction did sign extension, so it was cheaper to
>have chars be signed...

I've heard Dennis express some doubts about this decision in retrospect,
but it was a sensible thing to do at the time.  The cost penalty for
doing unsigned chars on the 11 is fairly high unless you do enough
optimization to discover that the expression in question ignores the
high bits anyway (e.g. by assigning the value to another char variable).
-- 
The 486 is to a modern CPU as a Jules  | Henry Spencer at U of Toronto Zoology
Verne reprint is to a modern SF novel. |  henry@zoo.toronto.edu   utzoo!henry

carroll@m.cs.uiuc.edu (08/01/90)

/* Written  1:22 pm  Jul 31, 1990 by henry@zoo.toronto.edu in m.cs.uiuc.edu:comp.lang.c */
In article <17181@haddock.ima.isc.com> karl@kelp.ima.isc.com (Karl Heuer) writes:
>>Side note: can anyone out there give a good explanation as to why
>>chars were *ever* signed in the first place,
>The pdp11's byte-to-word instruction did sign extension, so it was cheaper to
>have chars be signed...
I've heard Dennis express some doubts about this decision in retrospect,
but it was a sensible thing to do at the time.
/* End of text from m.cs.uiuc.edu:comp.lang.c */
The problem was that "signed" was a valid type modifier, but "unsigned" wasn't.
If chars were (by default) unsigned, they could be made signed, but if they
were signed, they couldn't be made unsigned. This means that under K&R(1) C,
if the default char type was signed, there was no way to have unsigned chars.
IMHO, this is a problem. (Now ANSI-fixed, at least).

Alan M. Carroll                Barbara/Marilyn in '92 :
carroll@cs.uiuc.edu            + This time, why not choose the better halves?
Epoch Development Team         
CS Grad / U of Ill @ Urbana    ...{ucbvax,pur-ee,convex}!cs.uiuc.edu!carroll

chris@mimsy.umd.edu (Chris Torek) (08/02/90)

In article <621@.tetrauk.UUCP> rick@.tetrauk.UUCP (Rick Jones) writes:
>Perhaps I finally understand the ANSII promotion rules at last!

Probably not. :-)  (Incidentally, `ANSI' has only one `I'; it is
`ASCII' that has two.)

Actually, the rule is fairly easy to state:  `In ANSI C, when an
unsigned type is promoted% to some other type, it becomes signed
(without changing value) if and only if the new type is actually
bigger.'  In practise, this means that you have to know whether
sizeof(short) < sizeof(int) and whether sizeof(char) < sizeof(int).

Alternatively, never let values promote without using a cast to
a non-promoting type; this avoids the problem entirely.
-----
% `Promotion' is not the same as `conversion' or `assignment'.
  See the standard (X3.159-1989) for an exact description.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris

carroll@m.cs.uiuc.edu (08/06/90)

/* Written 12:07 pm  Aug  2, 1990 by henry@zoo.toronto.edu in m.cs.uiuc.edu:comp.lang.c */
In article <4700058@m.cs.uiuc.edu> carroll@m.cs.uiuc.edu writes:
>The problem was that "signed" was a valid type modifier, but "unsigned" wasn't.
>If chars were (by default) unsigned, they could be made signed...

Um, excuse me?
/* End of text from m.cs.uiuc.edu:comp.lang.c */
Woops. Change "signed" <-> "unsigned". Got to get some more sleep.

peter@ficc.ferranti.com (Peter da Silva) (08/07/90)

In article <25836@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
> Actually, the rule is fairly easy to state:  `In ANSI C, when an
> unsigned type is promoted% to some other type, it becomes signed
> (without changing value) if and only if the new type is actually
> bigger.'  In practise, this means that you have to know whether
> sizeof(short) < sizeof(int) and whether sizeof(char) < sizeof(int).

What is the rationale for this? There's probably a good reason, but at
first glance it seems counterintuitive.
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>

ramsey@NCoast.ORG (Cedric Ramsey) (08/07/90)

In article <4700059@m.cs.uiuc.edu> carroll@m.cs.uiuc.edu writes:
>
>/* Written 12:07 pm  Aug  2, 1990 by henry@zoo.toronto.edu in m.cs.uiuc.edu:comp.lang.c */
>In article <4700058@m.cs.uiuc.edu> carroll@m.cs.uiuc.edu writes:
>>The problem was that "signed" was a valid type modifier, but "unsigned" wasn't.
>>If chars were (by default) unsigned, they could be made signed...
>
>Um, excuse me?
>/* End of text from m.cs.uiuc.edu:comp.lang.c */
>Woops. Change "signed" <-> "unsigned". Got to get some more sleep.


	Hello, I would like to throw in my two cents here, for what it's worth.
I though that chars were signed or unsigned for when used in expressions they
will be promoted to integer or unsigned as declared. Otherwise, who cares.
a char will be a char no matter what it's sign is. It will have the same
number of bits, which is the real problem; some chars are 8 bit others are 
7 some are 9, but thats another story. Anyway, that all that I have to say. 
As to the question, I don't know, I wasn't there. But if I didn't understand
the question I would have asked for clarification. Afterall, how can a 
programmer try to program a task without an understanding of what is 
to be done. That is from my perspective but then again I wasn't there and
don't know any of the underlying circumstances.

rjc@uk.ac.ed.cstr (Richard Caley) (08/25/90)

How about...

#define IsUnsigned(n) ((n-n-1) > 0 )

--
rjc@uk.ac.ed.cstr