Date: Fri, 9 Jan 2026 13:27:49 +0100
On 09/01/2026 11:32, Frederick Virchanza Gotham via Std-Proposals wrote:
> On Fri, Jan 9, 2026 at 12:39 AM Thiago Macieira wrote:
>>
>> In fact, the most common use won't use two pointers, but a pointer and a
>> generation counter. "atomic_pointer_pair" would be semantically the wrong
>> type.
>
>
> The type "int" started out as the natural integer type for a given
> architecture -- which means the width of the CPU registers.
>
> However when moving from x86_32 to x86_64, the RAX register was
> 64-Bit, but too many lack-lustre programmers had assumed 32-Bit int's
> in their code, and so 'int' wasn't bumped up to 64-Bit.
>
There are many pros and cons to consider when picking widths for
different integer types on a particular target architecture. While
source code compatibility with existing code is certainly one of the
considerations, it is only one factor amongst many.
> So now the natural type for a given architecture is not 'int', but
> rather 'intptr_t' -- and I actually use this type in my code when I
> want "the natural integer type".
>
No, "intptr_t" is not a "natural" type for anything except if you need a
signed integer type with the property that you can convert any pointer
to void to "intptr_t", then convert it back to a pointer to void, with
the result comparing equal to the original pointer to void. That's
/all/. (Normally, "uintptr_t" is a more logical choice than "intptr_t",
as memory addresses do not usually have a concept of sign.) The type is
optional in C and C++, and there are (admittedly rather niche)
architectures which do not support such types because they use very wide
pointers. But if you actually need to convert a pointer to an integer
type (perhaps for doing some alignment checks), "uintptr_t" is the type
to use.
If you need a general integer type that has at least 32 bits of range
and the fastest processing speed on a given architecture, C++ has you
covered - int_fast32_t. You could use that for your code if you like -
on most 64-bit architectures, it will be 64 bit. But it might be 32-bit
on some if it results in smaller and/or faster code.
The C++ standards don't care about the details of the machine
implementation - they care about providing the features you need to
write correct source code. It doesn't matter what size of registers you
have when picking an integer type - what matters most is the range of
the type is sufficient for the values you want it to support. The
secondary characteristic is efficiency (speed or size). So the
standards should not attempt to give any kind of "natural" integer type,
nor should you try to read such implications into the definitions of the
types. C and C++ provide exact width types [u]intNN_t, speed-optimised
types [u]int_fastNN_t, and size-optimised types [u]int_leastNN_t. You
can think of the standard integer types as being short-hand for balanced
or compromise types - "int" is "int_balanced_fast16_t", "short" is
"int_balanced_size16_t", "long" is "int_balanced_fast32_t", etc. A lot
of programmers can assume that "int" is at least 32-bit because that
comes out of other requirements (Windows, POSIX, etc.). But for
standard C++, "int" is just an integer type of at least 16 bits. And
"intptr_t" is optional and tells you nothing about its size or range.
> In choosing the name for the type "atomic_pointer_pair", the 'pointer'
> part really just means "the register width". That's why the member
> functions of atomic_pointer_pair will allow you to access either of
> the pointers as intptr_t, so that when you're writing a lockfree
> container you can have "pointer + counter".
That is just silly. Pick names that make sense for the task at hand.
Pointers and integer types are different concepts.
> On Fri, Jan 9, 2026 at 12:39 AM Thiago Macieira wrote:
>>
>> In fact, the most common use won't use two pointers, but a pointer and a
>> generation counter. "atomic_pointer_pair" would be semantically the wrong
>> type.
>
>
> The type "int" started out as the natural integer type for a given
> architecture -- which means the width of the CPU registers.
>
> However when moving from x86_32 to x86_64, the RAX register was
> 64-Bit, but too many lack-lustre programmers had assumed 32-Bit int's
> in their code, and so 'int' wasn't bumped up to 64-Bit.
>
There are many pros and cons to consider when picking widths for
different integer types on a particular target architecture. While
source code compatibility with existing code is certainly one of the
considerations, it is only one factor amongst many.
> So now the natural type for a given architecture is not 'int', but
> rather 'intptr_t' -- and I actually use this type in my code when I
> want "the natural integer type".
>
No, "intptr_t" is not a "natural" type for anything except if you need a
signed integer type with the property that you can convert any pointer
to void to "intptr_t", then convert it back to a pointer to void, with
the result comparing equal to the original pointer to void. That's
/all/. (Normally, "uintptr_t" is a more logical choice than "intptr_t",
as memory addresses do not usually have a concept of sign.) The type is
optional in C and C++, and there are (admittedly rather niche)
architectures which do not support such types because they use very wide
pointers. But if you actually need to convert a pointer to an integer
type (perhaps for doing some alignment checks), "uintptr_t" is the type
to use.
If you need a general integer type that has at least 32 bits of range
and the fastest processing speed on a given architecture, C++ has you
covered - int_fast32_t. You could use that for your code if you like -
on most 64-bit architectures, it will be 64 bit. But it might be 32-bit
on some if it results in smaller and/or faster code.
The C++ standards don't care about the details of the machine
implementation - they care about providing the features you need to
write correct source code. It doesn't matter what size of registers you
have when picking an integer type - what matters most is the range of
the type is sufficient for the values you want it to support. The
secondary characteristic is efficiency (speed or size). So the
standards should not attempt to give any kind of "natural" integer type,
nor should you try to read such implications into the definitions of the
types. C and C++ provide exact width types [u]intNN_t, speed-optimised
types [u]int_fastNN_t, and size-optimised types [u]int_leastNN_t. You
can think of the standard integer types as being short-hand for balanced
or compromise types - "int" is "int_balanced_fast16_t", "short" is
"int_balanced_size16_t", "long" is "int_balanced_fast32_t", etc. A lot
of programmers can assume that "int" is at least 32-bit because that
comes out of other requirements (Windows, POSIX, etc.). But for
standard C++, "int" is just an integer type of at least 16 bits. And
"intptr_t" is optional and tells you nothing about its size or range.
> In choosing the name for the type "atomic_pointer_pair", the 'pointer'
> part really just means "the register width". That's why the member
> functions of atomic_pointer_pair will allow you to access either of
> the pointers as intptr_t, so that when you're writing a lockfree
> container you can have "pointer + counter".
That is just silly. Pick names that make sense for the task at hand.
Pointers and integer types are different concepts.
Received on 2026-01-09 12:27:55
