On my platform (and on most of them I think) std::size_t
and std::ptrdiff_t
have the same size and the same alignment. Is there any platform where that is not true? In short: is it required by the standard?

- 57,834
- 11
- 73
- 112

- 1,559
- 9
- 15
3 Answers
In short: is it required by the standard?
No. The only requirement is from [support.types.layout]/2 and it is:
The type ptrdiff_t is an implementation-defined signed integer type that can hold the difference of two subscripts in an array object, as described in [expr.add].
There is paragraph 4
[ Note: It is recommended that implementations choose types for ptrdiff_t and size_t whose integer conversion ranks are no greater than that of signed long int unless a larger size is necessary to contain all the possible values. — end note ]
but notes are non-normative and it is only a recommendation, not a requirement.
std::size_t
is defined as
The type size_t is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object ([expr.sizeof]).
in paragraph 3 and it also has no requirement that they be the same.

- 171,901
- 28
- 288
- 402
-
You might also want to note the requirement for `size_t`, which is immediately after the requirement you have linked for `ptrdiff_t`. – Peter May 21 '20 at 13:54
-
@Peter Added into the answer – NathanOliver May 21 '20 at 13:57
-
On what platform is `ptrdiff_t` not a signed version of `size_t`? – Maxim Egorushkin May 21 '20 at 14:08
-
@MaximEgorushkin AFAIK, none. That said, there is no guarantee that will hold for all systems. – NathanOliver May 21 '20 at 14:10
-
What about 16-bit systems (without the huge code model)? In that case, `size_t` would naturally be 16 bits, but you'd expect `ptrdiff_t` to be larger so that you can have `char` arrays of size between 32K and 64K. Indeed there's a note at https://en.cppreference.com/w/cpp/types/ptrdiff_t that C++11 requires `ptrdiff_t` to be at least 17 bits wide. – Nate Eldredge May 21 '20 at 15:22
It is not required by the standard.
Note that the current crop of Intel processors have 48 bit pointers under the hood.
So personally I don't see it too far-fetched to conceive a 64 bit unsigned
for std::size_t
and a 49 bit signed type for a std::ptrdiff_t
. Although such a scheme would be a headache to implement.
More interestingly once chipsets evolve to have 64 bit pointers (we are some way off that being necessary), presumably std::ptrdiff_t
will have to be at least 65 bits! Personally therefore I keep in mind that one day sizeof(std::ptrdiff_t)
may be larger than sizeof(std::size_t)
.

- 231,907
- 34
- 361
- 483
-
Under the hood the pointers are still 64 bits. x86_64 requires the top 16 bits to be a copy of bit 47. ARM64 can ignore the top byte in a 64-bit pointer which one can use for tags. – Maxim Egorushkin May 21 '20 at 15:01
-
1@MaximEgorushkin: I was going to wade in with a contradiction, but I notice that, like me, you're a childhood Z80 programmer! I wrote some of the "sprite" code that made it into some of the commercial games: Sorcery for one. Note the hideous use of XOR! – Bathsheba May 21 '20 at 15:27
-
1Did you intend to say that Z80 was an 8-bit processor with 16-bit addresses? `xor` was the basis of many copy-protection/code-encryption back in those days, especially with undocumented R register, which you could not just step through in the debugger to decrypt the code. I may have played Sorcery back then! Truly high performance code used `push` to draw on the screen, because it was the fastest way to store a word and move to the previous write position. – Maxim Egorushkin May 21 '20 at 15:48
On my platform ...
std::size_t
andstd::ptrdiff_t
have the same size
How is this compliant?
C has (which I believe C++ inherits - if not let me know to delete) as UB in § J.2:
The result of subtracting two pointers is not representable in an object of type
ptrdiff_t
(6.5.6)."
This allows the type of ptrdiff_t
to be the signed counterpart of the unsigned size_t
.
When paired as such with no padding,
char a[PTRDIFF_MAX + (size_t)1]; // OK with enough memory in the location needed
size_t size_a = sizeof a; // OK
size_t diff0 = &a[sizeof a - 1] - &a[0]; // OK
ptrdiff_t diff1 = &a[sizeof a] - &a[0]; // UB
ptrdiff_t diff2 = %a[0] - &a[sizeof a]; // UB
Moral of the story: troubles with pointer subtraction (result type: ptrdiff_t
) may begin when the array element count exceeds PTRDIFF_MAX
.

- 143,097
- 13
- 135
- 256