ISO/ IEC JTC1/SC22/WG14 N708

						WG14 N708
Issues with size_t and ptrdiff_t
================================
Clive D.W. Feather
==================

The type /size_t/ is an unsigned integral type that is intended to hold
the size of objects in bytes and the offsets of structure members.
However, it appears that nothing prevents this type being as small as
/unsigned char/. If so, the behaviour of /sizeof (char [UCHAR_MAX + 1])/
is unclear.

The type /ptrdiff_t/ is a signed integral type that is intended to hold
the difference between pointers into the same array object. However, it
appears that nothing prevents this type being as small as /signed char/.
If so, the behaviour of:
    char s [SCHAR_MAX + 1];
    char *p = s + sizeof (s);
    p - s;
is unclear.

There are a number of possible approaches to these two problems.
Detailed changes are given for each. Each proposal could make certain
formerly strictly conforming programs require a diagnostic, but only
when they use a very large object in some way.


size_t
======

Option 1
--------
One possibility is to forbid the creation of objects whose size cannot
be represented in a /size_t/. Quality of implementation would therefore
force this type to be sufficiently large.

Add to the Constraints of subclause 6.5:

    A declaration shall not specify an object whose size (in bytes) is
    greater than the maximum value of an object of type /size_t/.

Option 2
--------
Alternatively, allow large objects to exist, but force a diagnostic if
/sizeof/ is used on an object that's too big.

Add a new Constraint to subclause 6.3.3.4:

    The /sizeof/ operator shall not be applied to an expression or to
    the name of a type such that the result is greater than the maximum
    value of an object of type /size_t/.

Add a new Constraint to subclause 6.4:

    A constant expression shall not be derived from an expansion of the
    /offsetof/ macro where the offset of the structure member (in bytes)
    is greater than the maximum value of an object of type /size_t/.

The latter constraint is not ideal, nor is it ideally placed. However,
constraints are not found in clause 7.


ptrdiff_t
=========

Option 1
--------
As with /size_t/, we could prohibit arrays large enough to be a problem:

Replace the Constraint of subclause 6.5.4.2 with:

    The expression delimited by [ and ] (which specifies the size of an
    array) shall be an integral constant expression that has a value
    greater than zero and less than or equal to the minimum of the
    absolute values of the minimum and maximum values of an object of
    type /ptrdiff_t/.

Option 2
--------
Alternatively, since pointer subtraction is much more likely to be
dynamic, it may suffice to allow the result to overflow.

Change the last sentence of 6.3.6 paragraph 9 to read:

    Unless both pointers point to elements of the same array object, or
    one past the last element of the array object, or if the result is
    not representable as a value of type /ptrdiff_t/, the behaviour is
    undefined. [61]

In this case, it may be worth putting a minimum range on /ptrdiff_t/.

Append to subclause 7.1.6 (<stddef.h>) paragraph 2:

    The type /ptrdiff_t/ shall be capable of representing all values in
    the range -65535 to +65535 inclusive.

[The numbers are taken from the "bytes in an object" translation limit.]