size_t and ptr_diff_t

B

Bob Cassel

I have the idea that ptr_diff_t had to be the same size as size_t from
Plauger's "The Standard C Library," where he states "... It is always
the signed type that has the same number of bits as the4 unsigned type
chosen for size_t..." This language would not rule out one being int
and the other long so long as sizeof(int)==sizeof(long) for the
implementation.

Now I can't see anywhere in the standard that would require that, at
least not directly, and it seems that a size_t of unsigned int and a
prtdiff_t of long (where int and long are different sizes) would be
possible. C99 defines SIZE_MAX as being at least 65535, and
PTRDIFF_MIN/MAX as being at least -/+65535.

So do size_t and ptr_diff_t have to be the same size (or base type) or
not?
 
M

Malcolm McLean

Bob Cassel said:
I have the idea that ptr_diff_t had to be the same size as size_t from
Plauger's "The Standard C Library," where he states "... It is always
the signed type that has the same number of bits as the4 unsigned type
chosen for size_t..." This language would not rule out one being int
and the other long so long as sizeof(int)==sizeof(long) for the
implementation.

Now I can't see anywhere in the standard that would require that, at
least not directly, and it seems that a size_t of unsigned int and a
prtdiff_t of long (where int and long are different sizes) would be
possible. C99 defines SIZE_MAX as being at least 65535, and
PTRDIFF_MIN/MAX as being at least -/+65535.

So do size_t and ptr_diff_t have to be the same size (or base type) or
not?
The problem is that size_t is usally the width of the address bus, because
the biggest object you can hold in memory is all of memory.
ptrdiff_t has to represent the difference between two pointers, so it must
be signed. Therefore it needs an extra bit.
However that is probably inefficient. Most pointers are not character
pointers anyway. In practise the promise for subtracting very distant
character pointers is not honoured, and ptrdiff_t is a signed type with the
same number of bits as size_t.
 
F

Flash Gordon

Malcolm McLean wrote, On 23/08/07 21:41:
They are not required to be the same size. In fact, with the minimum
requirements you specify (which are correct) it would make sense on a 16
bit system to have size_t as a 16 bit unsigned integer (unsigned int
probably) and ptrdiff_t a signed 32 bit integer (long probably). The
same sort of thing applies to a 64 bit system which limits the maximum
size of a single object to (2^32)-1, which would not be unreasonable.
The problem is that size_t is usally the width of the address bus,
because the biggest object you can hold in memory is all of memory.

Historically some systems have limited the largest single object to be
much smaller than the address bus allows. For example only allowing
objects up to 64K on an 80286 or 68000 for efficiency reasons.
ptrdiff_t has to represent the difference between two pointers, so it
must be signed. Therefore it needs an extra bit.
However that is probably inefficient. Most pointers are not character
pointers anyway. In practise the promise for subtracting very distant
character pointers is not honoured, and ptrdiff_t is a signed type with
the same number of bits as size_t.

True. In practical terms I would be very surprised if anyone allocated a
single object as large as half the size the address bus can allocate, so
a ptrdiff_t type the same width as the address bus should be fine.
 
C

christian.bau

The problem is that size_t is usally the width of the address bus, because
the biggest object you can hold in memory is all of memory.
ptrdiff_t has to represent the difference between two pointers, so it must
be signed. Therefore it needs an extra bit.
However that is probably inefficient. Most pointers are not character
pointers anyway. In practise the promise for subtracting very distant
character pointers is not honoured, and ptrdiff_t is a signed type with the
same number of bits as size_t.

I think it is highly unlikely that size_t is in any way related to the
width of the address bus. For example, I can tell my compiler to
generate 32 bit code or 64 bit code, and size_t is different
(actually, I think it is a 32 bit unsigned long in one case and a 64
bit unsigned long in the other case), but the width of the address bus
is exactly the same.
 
K

Keith Thompson

Malcolm McLean said:
The problem is that size_t is usally the width of the address bus,
because the biggest object you can hold in memory is all of memory.

That's commonly true, but the standard doesn't require it, and there
have been systems where the maximum size of an object is less than all
of memory. Note that both size_t and ptrdiff_t (note the spelling)
are meaningful only for single objects. size_t is the result of
sizeof, which can only be applied to a single object; ptrdiff_t is the
result of pointer subtraction, which invokes undefined behavior unless
both pointers point into the same object.
ptrdiff_t has to represent the difference between two pointers, so it
must be signed. Therefore it needs an extra bit.
However that is probably inefficient. Most pointers are not character
pointers anyway. In practise the promise for subtracting very distant
character pointers is not honoured, and ptrdiff_t is a signed type
with the same number of bits as size_t.

True. There's no explicit requirement in the standard for size_t and
ptrdiff_t to be the same size, but they commonly are (I've never heard
of a system where they aren't). It could make sense to make ptrdiff_t
larger because it "wastes" one bit for the sign, but that's rarely
done, if ever.
 
E

Eric Sosman

Malcolm McLean wrote On 08/23/07 16:41,:
The problem is that size_t is usally the width of the address bus
[...]

Why do you keep on making this claim after it's been
refuted over and over again?

The machine in front of me at this moment has a 34-bit
address bus (it's a creaky old machine; the shoemaker's
children go barefoot). Depending on the compiler options,
size_t is either 32 or 64 bits wide.
 
P

pete

Malcolm said:
In practise the promise for subtracting very distant
character pointers is not honoured,
and ptrdiff_t is a signed type with the
same number of bits as size_t.

There's no promise,
unless a program stays inside the minimum environmental limits,
and then the promise is kept.

N869

5.2.4.1 Translation limits
-- 65535 bytes in an object (in a hosted environment only)


7.18.3 Limits of other integer types
-- limits of ptrdiff_t
PTRDIFF_MIN -65535
PTRDIFF_MAX +65535


6.5.6 Additive operators
[#9] 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.
 
J

Jack Klein

I think it is highly unlikely that size_t is in any way related to the
width of the address bus. For example, I can tell my compiler to
generate 32 bit code or 64 bit code, and size_t is different
(actually, I think it is a 32 bit unsigned long in one case and a 64
bit unsigned long in the other case), but the width of the address bus
is exactly the same.

As much as I dislike the idea of standing up for Malcolm, I think his
meaning is quite logical even if his use of the term "address bus" is
ill-advised. If you replace that by saying:

"size_t is usually the smallest unsigned integer type that can hold
all the bits in a pointer to char", it makes more sense.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
 
M

Malcolm McLean

Eric Sosman said:
Malcolm McLean wrote On 08/23/07 16:41,:
The problem is that size_t is usally the width of the address bus
[...]

Why do you keep on making this claim after it's been
refuted over and over again?

The machine in front of me at this moment has a 34-bit
address bus (it's a creaky old machine; the shoemaker's
children go barefoot). Depending on the compiler options,
size_t is either 32 or 64 bits wide.
Usually.
You can of course implement a compiler with 42 bit pointers on top of a
32-bit architecture, and have correspondingly weird rules for size_t.
However it is not normal to do that sort of thing.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top