Re: C89, size_t, and long



Eric Sosman wrote:
Yevgen Muntyan wrote On 03/14/07 14:26,:
Hey,

I was reading C99 Rationale, and it has the following two QUIET CHANGE
paragraphs:

6.5.3.4: "With the introduction of the long long and extended integer
types, the sizeof operator may yield a value that exceeds the range
of an unsigned long."

6.5.6: "With the introduction of the long long and extended integer
types, the subtraction of pointers may return a value that exceeds the
range of a long."

Was it required by C89 that result of sizeof() fits into unsigned long,
and that pointer subtraction result fits into long?

"Yes" and "Almost," respectively. C89 offered a fixed
set of integer types, of which {,un}signed long was the widest.
The implementation was free to provide additional types that
behaved like integers, but they were not "integer types" as
C89 defined them. C89 also required that size_t and ptrdiff_t
be aliases for "integer types," so they could not be wider than
long. If an implementation offered wider types, they were not
"integer types" and hence were not candidates for size_t and
ptrdiff_t.

On machines whose longs are the same width as their pointers
(more generally, no wider than their pointers), this means that
ptrdiff_t cannot be wide enough to express the result of all
pointer subtractions. An easy example:

char *p = malloc(LONG_MAX + 2u); /* assume success */
char *q = p + LONG_MAX + 2u;
ptrdiff_t delta = q - p;

We will now have p < q but (probably) delta < 0.

If yes, then MS
Win64 implementation is not C89-conforming (while sizeof case may be
arguable, I guess, we certainly can ask to malloc more than ULONG_MAX
bytes, and get pointer arithmetics which needs more than (unsigned)
long). If no, why these two paragraphs, if programs which relied on long
being big enough were already broken?

I don't know MS' Win64 implementation well enough to comment
on whether it's broken or not.

It has 32-bit long, same as int, and naturally 64-bit size_t.

As for programs that assumed
size_t and ptrdiff_t were no wider than long, no: They were not
broken under C89's rules, because C89 implied the truth of the
assumption.

Then these programs may be broken on Win64, right? Say, this code:

void do_something (void *buf, unsigned long len)
{
memset (buf, 1, len);
}

int main (void)
{
size_t i;
size_t size = BIG_NUMBER;
char *p = malloc (size);
if (p)
{
do_something (p, size);
assert (p[size-1]);
}
return 0;
}

BIG_NUMBER can be defined as some square root of SIZE_MAX+1 multiplied
by two or something, so we don't need to invent functions which get
us a big buffer. I guess MS estimated somehow how much of their code
uses long as 32-bit int, and decided it's more than code which uses
unsigned long as size_t. Anyway, is MS Win64 implementation not
C89-conforming (it's an important thing, isn't it)? Or I do miss
something?

Thanks,
Yevgen
.



Relevant Pages

  • Re: size_t
    ... common integer types like char, short, int .. ... the idea for size_t was to provide support for various architechtures in a ... integer type as offset to the array on platforms where, say, int would be 32 ... bit but pointers 64 bit. ...
    (comp.lang.cpp)
  • Re: Decreasing order of address within main
    ... but by CPU itself (if it uses memory in big or little endian). ... you're comparing pointers to different objects which is UB. ... integer types capable of holding object pointers. ...
    (comp.lang.c)
  • Re: cast pointer to int
    ... Apparently a very bad tutorial about pointers in C, ... with quite frequently has the following sizes for integer types: ... Another has char, short, int, and long all 1 byte. ... There are platforms where the value of a pointer is too large to fit ...
    (comp.lang.c)
  • Re: A malloc question
    ... all signed integer types and all unsigned integer types ... pointers, but I agree that all struct pointers have the same ... representation ...
    (comp.lang.c)
  • Re: C89, size_t, and long
    ... and it has the following two QUIET CHANGE ... If an implementation offered wider types, ... On machines whose longs are the same width as their pointers ... Win64 implementation is not C89-conforming (while sizeof case may be ...
    (comp.lang.c)