Does size_t have the same size and alignment as ptrdiff_t?
Asked Answered
B

3

7

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?

Birdella answered 21/5, 2020 at 13:41 Comment(0)
M
6

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.

Maud answered 21/5, 2020 at 13:51 Comment(5)
You might also want to note the requirement for size_t, which is immediately after the requirement you have linked for ptrdiff_t.Hypogeous
@Hypogeous Added into the answerMaud
On what platform is ptrdiff_t not a signed version of size_t?Indistinguishable
@MaximEgorushkin AFAIK, none. That said, there is no guarantee that will hold for all systems.Maud
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 en.cppreference.com/w/cpp/types/ptrdiff_t that C++11 requires ptrdiff_t to be at least 17 bits wide.Brutify
D
3

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).

Dictum answered 21/5, 2020 at 14:36 Comment(3)
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.Indistinguishable
@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!Dictum
Did 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.Indistinguishable
T
0

On my platform ... std::size_t and std::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.

Tearoom answered 21/5, 2020 at 23:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.