On 01/06/2021 20:17, Keith Thompson wrote:
> David Brown <
david...@hesbynett.no> writes:
>> On 01/06/2021 18:00, Manfred wrote:
> [...]
>>> I think this would be problematic as well, or at least useless and
>>> confusing.
>>> The idea for intmax_t is to give a standard name to the widest integer
>>> type that is available, which is by definition implementation defined.
>>> Having intmax_t an alias for "long long" would change its meaning to the
>>> widest /standard/ integer type defined by the standard itself - a
>>> useless repetition (we have "long long" for that), and confusing too,
>>> given its change in meaning.
>>
>> Yes, that is all true. The point is not to find another useful purpose
>> for intmax_t - the point is to get rid of it, marking it as deprecated,
>> but to do so in a way that won't break existing code.
>>
>> I am at a loss to understand why anyone would have a use for intmax_t in
>> the first place. When would you want an integer type whose sole
>> characteristic is "big" ? To me, it is logical to want a type that is
>> at least N bits, or exactly N bits. These requirements are covered by
>> the normal "short", "int", "long" and "long long" types, or - better for
>> my use, but not necessarily other people's - the <stdint.h> fixed size
>> types. "intmax_t" gives you absolutely /nothing/ that "long long" does not.
>
> Suppose you have a type foo_t, and all you know is that it's a signed
> integer type. You can print it using printf("%ju", (intmax_t)n).
And if you know "long long" is the largest standard type, you can print
it with "%llu". The reality is that it is currently exactly the same.
intmax_t doesn't let you print anything that you can't print with "long
long" in any existing implementations, and is seems unlikely to do so in
the future.
If implementations regularly had integer types that were bigger than
"long long" then "intmax_t" could have been useful in such cases. It
could be seen as a good reason for introducing intmax_t in the first
place. The reality, however, is different.
I suspect an issue here is that compilers and standard libraries are
often developed somewhat independently - but the introduction of a
larger integer type in a compiler would require changes to the libraries
used, possibly also the ABI for the platform. It's one thing to accept
such chicken-and-egg challenges for a major new C revision, such as the
introduction of "long long" in C99, but quite another to have it for
compiler-specific extensions along the way.
> (Or in C++ you can use std::cout << n, but intmax_t is inherited from
> C's standard library.)
>
C++ does not have the problems or excuses of C here. printf is a pain
because it is a variadic function with types unknown at declaration and
compile time (of the printf implementation). For C++, an implementation
can easily add an overload for << with whatever types the compiler supports.
> Or suppose you're implementing an arbitrary-width integer type as
> an array of fixed-width integers. You might want each element to
> be as wide as possible, because arithmetic on a 2*N-bit integer is
> likely to be faster than synthesizing it from two N-bit integers.
> (That's assuming that, for example, 128-bit integer arithmetic
> isn't drastically less efficient than 64-bit integer arithmetic.)
>
You need to know the sizes of your integers here. intmax_t, specified
merely as "at least as big as long long", is useless. For such tasks,
you use the <stdint.h> types in general, and possibly compiler-specific
extensions like __int128. You don't use intmax_t. (At least, /I/ can't
see how it would be helpful here.)
>> Given that there are, as far as we know, no implementations where
>> intmax_t does not correspond directly to "long long", I would like to
>> see "intmax_t" be dropped to the maximum extent allowable by backwards
>> compatibility.
>
> I'd *like* to keep intmax_t and make it work the way it was intended,
> but ABI issues made that impractical. (I'm guessing those issues
> weren't anticipated when intmax_t was added in C99.) Deprecating it
> might be the least bad solution.
Fair enough.
>
>>> As far as I understand the purpose for intmax_t is to allow for (sort
>>> of) 'standard' prototypes of functions like imaxabs, imaxdiv, strtoimax,
>>> etc that are supposed to operate on larger integer types - these are the
>>> only functions that take this kind of arguments.
>>> The confusing part is that all of these facilities are implementation
>>> dependent, so even if they are part of the standard they are /not/
>>> portable, meaning that the programmer is supposed (the way I see it) to
>>> use them under the guard of appropriate preprocessor directives.
>>>
>>> The use for them is to allow the programmer to use some optimized
>>> routines for larger types, if available.
>>
>> But they don't allow that. If you are trying to make optimised routines
>> for larger types, you need to know your sizes - you either use
>> implementation extensions (like __int128), or fixed size types, or if
>> you need maximal portability, you use "int_fast64_t".
>
> And my impression (which could be mistaken) is that __int128 is not an
> extended integer type partly *because* it would require making intmax_t
> 128 bits, which would cause ABI problems. That, and __int128 is
> unfinished (some features are missing), but if it could have been made
> an extended integer type perhaps more effort would have been spent
> making it fully functional.
>
Agreed.
>>> For example, in case operations like ldiv are needed on 128 bit
>>> integers, then IF the implementation supports 128 bit intmax_t then
>>> imaxdiv can be a better choice rather than implementing your own routine
>>> - note that /IF/ is the keyword here, that should map directly to
>>> appropriate #if directives.
>>
>> The situation we have now is that on a compiler like gcc you can get
>> 128-bit division using __int128, but /not/ using intmax_t. It is a
>> useless type.
>
> I suspect it's useful enough for some purposes. There's probably code
> out there that uses __int128 that doesn't need 128-bit division.
>
I might have been unclear there - I meant "intmax_t" is a useless type.
__int128 is useful as it is (albeit not often useful). Adding abs,
div, etc., support to __int128 would not make it any more useful.