On Mon, 2007-03-26 at 10:57 +0200, Schwarz, Konrad wrote: > > -----Original Message----- > > From: Clive D.W. Feather [mailto:[EMAIL PROTECTED] > > > 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