lua-users home
lua-l archive

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


On Wed, May 01, 2013 at 11:00:18AM -0300, Roberto Ierusalimschy wrote:
> > On Tue, Apr 30, 2013 at 06:51:23PM -0700, Tim Hill wrote:
> > > 
> > > But the point is that the C "standard" leaves some things so open that
> > > it's very difficult to write code without making some guesses. Width of an
> > > integer?
> > 
> > If you could provide concrete examples, then it would be easier to discuss.
> 
> I already mentioned one: pointer difference and ptrdiff_t. According to
> the standard, they are mostly useless:
> 
>   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.  IF THE RESULT IS NOT REPRESENTABLE IN AN OBJECT OF
>   THAT TYPE, THE BEHAVIOR IS UNDEFINED.
> 
> (emphasis added.) Nothing in the standard connects the minimum size of
> ptrdiff_t with size_t. So, an arbitrary subtraction of pointers to
> an array larger than 64K can fail.  (To make things worse, note that
> it does not cause an undefined result, but an undefined behavior! Your
> program can simply crash for doing the subtraction.)

I was aware of what you were referring too. But how is the issue with
ptrdiff_t any different from, say, `LLONG_MAX * 2'? Signed overflow is
undefined generally.

I admit it's lamentable that pointer arithmetic is signed, but I suspect it
would be tricky to get unsigned semantics to work on segmented architetures.
(I've also heard of at least one archiecture still used today where C's
unsigned modulo arithmetic has to be emulated, and it decreases performance
considerably.)

So... sure, there are lots of things we'd all like to change about C and
many other languages we use regularly. So what? I just don't see how it
changes the ability to write portable code, or the "portability" of C
applications. For every additional guarantee C might add, it would likely
exclude actual hardware.

The more portable the C application, the fewer features it can depend upon.
But I don't understand what the viable alternative is. You can write
portable applications with well-defined contraints. You can bail out of a
compilation if CHAR_BIT != 8 && UINT_MAX < 4294967295UL, and you've lost
nothing. But others can choose to plow ahead if they want.

> In Lua, we assume that the size of ptrdiff_t is at least the size of
> size_t and avoid pointer subtraction of pointers to chars. (As size_t
> works with chars and ptrdiff_t works with elements, elements with
> size >= 2 will fit.) But the standard does not garantee our
> hypothesis.

But you don't have to assume anything. The macro PTRDIFF_MAX can be used to
limit the size of object allocations if necessary.

Files on 32-bit systems can be much larger than 4GB. Are we to complain that
C doesn't have a 128-bit type so we could easily represent the size of such
objects? Is it impossible or impractical to write portable applications that
can process data in amounts greater than representable by size_t? I don't
see how the issue with ptrdiff_t and pointer arithmetic is categorically any
different than fread() and a size_t accumulator. In both cases the
simplistic and naive method will fail because of finite architecture
limitations. Neither should be more-or-less obvious if one has actually
taken the time to read the standard, as too few people do.

I understand your complaint. But I'm having trouble distinguishing it from
worrying about whether all the oxygen molecules in my room will randomly
move to the ceiling. Would it make the universe simpler and more consistent
if God guaranteed it wouldn't happen?