Re: SOLUTION (Re: Style question: comparison between signed and unsigned?)

Andrew G. Morgan (morgan@parc.power.net)
Sat, 27 Sep 1997 08:19:54 -0700 (PDT)


Gerard Roudier wrote:
> > Your solution is close to being correct, POSIXwise. The completely
> > "compliant" way of doing this is
> >
> > ssize_t read_return_value;
> > size_t nr_of_bytes_read;
....
> > nr_of_bytes_read = (size_t) read_return_value;
>
> Your cast is just stupid in my opinion.
> Your are just assuming that the called function only returns > 0 when it
> does not return -1.

Since everyone and his dog has chipped in here and reasonably convincing
arguments have been banded about, perhaps we can have some
concensus/agreement to differ and move on?

"Strictly" speaking, I think the gcc crowd have done a good job of trying to
make sense of 'C'. Appendix A6.5 of K&R II casts a murky shadow over this
whole discussion: promotion of ints to unsigneds and their architecture
dependent behavior for int<->long conversions.

My take on this is that sizeof() should return something signed and not
unsigned since who ever made a structure half the size of the address space?
But that's my take and a lot of my elders and betters got to make the
choice without ever asking me ;^) [It seems that Ted and I would have
written the 'C' spec differently!]

Regarding 'read()', POSIX and ISO are simply different..

POSIX: int read(int fd, void *buf, unsigned int nbytes)
ISO: ssize_t read(int fd, void *buf, size_t nbytes)

the latter attempts to accomodate the possibility that the address space is
larger than what can be held in an unsigned int by introducing some new
types. When you look at the POSIX prototype, you do wonder what is supposed
to happen when nbytes is larger than the maximum value that an int can hold
(namely, how does its return value report such a large read?). In reality,
no-one is ever going to find they can read that much data in a single read
but the whole issue is one of principle and that means people want to argue
about it!

On this point, I realized that I needed to take a second look and
'understand' what a ssize_t is.. Before this discussion began, I have to
confess that I had assumed it was a 'signed'-number with one-bit less of a
positive range than the 'size_t'. However, thinking about it in this
context and trying to make some sense of the aside on p386 of Lewine's POSIX
book (definition for read()), it would seem that it is more properly
described as exactly the same as a size_t but with indiviual value(s)
reserved for errors. (If this is wrong, I would be grateful for a pointer to
the actual definition..) In the ISO convention, then, comparing the return
value of read with a negative integer _is_ worthy of a comment from gcc
-Wall..

The bottom line is that POSIX and ISO read()'s are different and, given the
implicit arithmetic conversions of 'C', we are just wandering around in
circles trying convince each other that the better one is the one we prefer
to use. Despite the fact that all the manuals indicate that read uses ISO
conventions, a look at the kernel source indicates that kernel has an
independent notion of the prototype for read (2.0.31pre9):

asmlinkage int sys_read(unsigned int fd,char * buf,int count)

[with int -> long for 64 bit machines] So what has resulted is different
people "knowing" they are right about their own opinion. :^)

Perhaps we should agree (or defer to Linus) on which convention we are going
to support and tidy up the respective source? Whatever, I think it is clear
that this is likely to be an unpopular "feature" of gcc so an _extra_
command line option should be available to turn it off (without losing all
the other -Wall benefits).

[That was a lot longer than I had planned. But I don't anticipate emailing
about this again...]

Cheers

Andrew

-- 
               Linux-PAM, libpwdb, Orange-Linux and Linux-GSS
                  http://parc.power.net/morgan/index.html

-- 
               Linux-PAM, libpwdb, Orange-Linux and Linux-GSS
                  http://parc.power.net/morgan/index.html