bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: source(builtin) and read(2)


From: Nick Stoughton
Subject: RE: source(builtin) and read(2)
Date: Mon, 26 Mar 2007 11:25:36 -0700

On Mon, 2007-03-26 at 10:57 +0200, Schwarz, Konrad wrote:
> > -----Original Message-----
> > From: Clive D.W. Feather [mailto:address@hidden 
> > > While we're at it, I would be interested in the rational 
> > for "inventing"
> > > ssize_t and not using ptrdiff_t instead, if anyone would care to 
> > > comment.
> > 
> > size_t has to be able to hold the size of the largest object. 
> > It is an unsigned type.
> > 
> > ptrdiff_t has to be able to hold the largest difference 
> > between two pointers; it is a signed type.
> > 
> > The two need not be a signed/unsigned pair. For example, if a 
> > system has a maximum object size of 64,000 bytes, then size_t 
> > needs to be at least 16 bits but ptrdiff_t needs to be at 
> > least 17 bits. Thus it would be legitimate for size_t to be 
> > (16 bit) unsigned short but ptrdiff_t to be
> > (32 bit) signed int.
> > 
> > ssize_t is the signed type corresponding to size_t. In the 
> > above example, it is required to be signed short. It's 
> > possible for a legitimate subtraction of two pointers to 
> > generate a value that can't fit in ssize_t.
> > However, because size_t and ssize_t are a signed/unsigned 
> > pair, they have useful properties (for example, when dealing 
> > with varargs lists).
> 
> Ok.
> 
> I see that e.g.,
> http://www.opengroup.org/onlinepubs/009695399/functions/read.html makes
> clear that "If the value of nbyte is greater than {SSIZE_MAX}, the
> result is implementation-defined.", so these types of functions can't
> deal with arbitrary objects (in the case that sizeof (ssize_t) < sizeof
> (ptrdiff_t)) anyhow.
> 
> If ptrdiff_t had been used as the return type for these functions, this
> restriction could have been lifted, since per definition, a ptrdiff_t
> can represent the size of all objects.  This would seem to have greater
> utility than the ability to interchange ssize_t and size_t when dealing
> with varargs lists.

Personal opinion only ... and speaking from (an imperfect) memory ...

size_t and ssize_t are types intended to convey information about size
of objects. We invented ssize_t because functions like read() return
either the size of the object they read, or -1 on error, so we needed a
signed type. Note also that the C standard defines fread() as returning
a size_t (it uses 0 as the error indicator).

ptrdiff_t is a very different sort of size: C99 says "When two pointers
are subtracted, both shall point to elements of the same array object,
or one past the last element of the array object; the result is the
difference of the subscripts of the two array elements. The size of the
result is implementation-defined, and its type (a signed integer type)
is ptrdiff_t defined in the <stddef.h> header."

As such, this definition in no way, shape, or form describes what read()
is returning. I guess you could describe the result as the difference in
a pointer to the end of the object read minus the original pointer to
the beginning of the buffer, but that is kind of stretching things in my
mind.

What read() returns is either the size of the object it read (so size_t
would be perfect for this), or -1 (which you can't store in a size_t).

Before we had ssize_t, as far as I can recall, read returned an int
(long, long, ago!). This is a better choice of type than ptrdiff_t, but
not as good as ssize_t.

As to the original question ... can a system that implements ssize_t
with a SSIZE_MAX of 56k conform to POSIX? As far as I can see, I don't
see why not. I agree that it is unnatural, but I can find nothing that
prohibits it. Most (if not all) interfaces that return ssize_t values
state that the results are implementation defined if you ask for more
than SSIZE_MAX bytes. If their implementation defines that a read of
>56k returns -1, then absolutely, they are conforming. If their
implementation defines that a read of >56k+1 returns >56k (assuming that
there was that much data available), then they are in slightly more
murky waters ... since the resulting value, while storable in an object
of sizeof(ssize_t) is not a legal member of the class of values that may
be stored in the object. And in that case, why did they choose to make
SSIZE_MAX this strange value in the first place?


> 
> >From C89/C99 I see that "size_t [...] is the unsigned integer type of
> the result of the sizeof operator" but not that objects up to 1 <<
> sizeof (size_t) * CHAR_BIT need to be supported by the implementation
> (e.g., in the above example, the implementation could defined the
> maximum object size as 1 << 15 bytes, and then ptrdiff_t and size_t
> could be a signed/unsigned pair).  In fact, this is the situation in all
> ABIs I have ever looked at.
> 
> Technically, having sizeof (ptrdiff_t) != sizeof (size_t) seems wrong
> for a wide class of CPU architectures, because both at some point should
> reflect the width of the registers used for addressing.
> 
> Was there ever any pressure from implementers for introducing ssize_t in
> lieu of ptrdiff_t?
> 
> Regards,
> 
> Konrad
> 

-- 
Nick Stoughton                          Cell: 510 388 1413
USENIX Standards Liaison                Fax:  510 548 5738





reply via email to

[Prev in Thread] Current Thread [Next in Thread]