https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119170
--- Comment #12 from Kang-Che Sung <Explorer09 at gmail dot com> --- Allow me to clarify some things. (In reply to Alejandro Colomar from comment #10)> > > The `_Widthof` > > operator working with traditional integer types is a plus but not a > > necessity. > > Here's an example of a use case of _Widthof with normal integers: > > $ grepc -htfd csrand_uniform32 . > static uint32_t > csrand_uniform32(uint32_t n) > { > uint32_t bound, rem; > uint64_t r, mult; > > if (n == 0) > return csrand32(); > > bound = -n % n; // analogous to `2^32 % n`, since `x % y == (x-y) % y` > > do { > r = csrand32(); > mult = r * n; > rem = mult; // analogous to `mult % 2^32` > } while (rem < bound); // p = (2^32 % n) / 2^32; W.C.: n=2^31+1, p=0.5 > > r = mult >> WIDTHOF(n); // analogous to `mult / 2^32` > > return r; > } > > Admittedly, I could hard-code a 32 there (just like it's hard-coded in the > function name, and local variables). However, I think that's more brittle, > and if I paste this code elsewhere and make the function work for uint64_t, > I'd like to need minimal changes, so WIDTHOF() helps make it more robust. I do have such use case in mind. And I am already able to imagine how useful it is if `_Widthof` can apply to many integer type synonyms. E.g. `_Widthof(off_t)`, `_Widthof(pid_t)`, `_Widthof(uid_t)`, `_Widthof(time_t)`, etc. As the width of these types can be retrieved via the `sizeof(T) * CHAR_BIT` fallback, I said the `_Widthof` operator on these types is not a "necessity". That leaves only the bit width of `_BitInt(N)` being the primary reason of introducing the operator. > > I show the implementation with CHAR_BIT and that making it work for _BitInt > would be harder (it would involve popcount, and can't make it a constant > expression at the moment). Acknowledged. > > > ### `_Minof(Type)` and `_Maxof(Type)` > > > > I'm personally skeptical of these two. And, if I have the decision power, I > > wish these two operators be made as votes separate from the `_Widthof` > > voting. > > I'm on the other side: I could live without _Widthof (except for the use > within csrand_uniform32(), I only use it for implementing _Minof and > _Maxof), but certainly need _Minof and _Maxof often. > I had a use case in mind that needs `IS_SIGNED()` as well as `MAXOF()`: This macro can scan an integer from a string and it intelligently detects whether the signed or unsigned "strto*" function should be used. ```c intmax_t scan_integer_signed(const char *str, intmax_t max) { intmax_t val = strtoimax(str, nullptr, 10); assert(val <= max); return val; } uintmax_t scan_integer_unsigned(const char *str, uintmax_t max) { uintmax_t val = strtoumax(str, nullptr, 10); assert(val <= max); return val; } #define SCAN_INTEGER(str, Type) \ (IS_SIGNED(Type) ? (Type)scan_integer_signed(str, MAXOF(Type)) : \ (Type)scan_integer_unsigned(str, MAXOF(Type))) ``` I'm not saying that `_Minof` and `_Maxof` are useless. It just occurs to me that there is no strong reason for standardizing them as keywords, comparing to usual idioms. (I would say I stand for the motto of "if it ain't broke, don't fix it".) > > > > > With the inclusion of `_Widthof`, and the mandating of two's complement > > representation for signed integers since C23, the `_Minof` and `_Maxof` > > expressions would be **implementable in one way only**. > > Not really true. I implement them differently than you. > > Which means I'd have to go and check why both your implementation and mine > do the same thing. > > [...] > > I certainly would prefer to avoid reviewing that code. Or writing it. I > don't feel safe. > > > Yes, there is only one way to implement these, as like the code above. > > As I showed, I have a different implementation. This statement is false. Unimportant differences, I would say. It's unlikely that compiler or libc writers would come up anything that is radically different from the syntax you and I have mentioned. "<< 1" and "* 2" are equivalent, and utype_max(T) being ((T) -1) is a usual simplification when utilizing the wrap-over arithmetic of unsigned integer types (and I know ((T) ~0) works as well). That is what I meant when I said there's "one way" of implementing it. Ignoring small differences. > > > > > I have multiple concerns with the `_Minof` and `_Maxof` proposal currently: > > * There are not technically necessary, and when programs need them, they are > > trivially implementable. (Standardizing them as keywords would only > > introduce noise to the language.) > > I wouldn't call the above trivial. > The programmer who had to review my implementation certainly didn't feel > safe: > <https://github.com/shadow-maint/shadow/pull/896#discussion_r1659894055> Unfortunately this doesn't convince me. I know your position - you want this to be available as a compiler builtin, and I support that. However, there are many code out there that aim for older versions of the standard, thus pushing this into C2x would not, AFAICT, solve the concerns of other programmers when the macro code needs a fallback (for pre-C2x compilers). I would say making `_Maxof` a compiler built-in does not require the keyword to be standardized, and sometime it would be better for this built-in to be left as an extension, not mandatory for an implementation.