On Wed, Oct 15, 2025 at 03:30:11PM +0200, Alejandro Colomar wrote:
> Hi Michael,
>
> On Wed, Oct 15, 2025 at 02:47:46PM +0200, Michael Matz wrote:
> > Hello,
> >
> > On Tue, 14 Oct 2025, Alejandro Colomar wrote:
> >
> > > Because bool is entirely different from the other regular integer types,
> > > and has entirely different rules,
> >
> > Why do you say that? bool and its operations is a normal finite algebra
> > on an ordered set, the only thing being that its add/mul are saturating
> > and have "funny" colloquial names (namely "or" and "and"):
> >
> > add == or ; mul == and
>
> Saturating arithmetics are what make it different, IMO.
>
> > Because the set is finite and fully ordered comparison makes (a) sense,
> > and the (b) max/min exists; and because it is so very small these two
> > operations actually coincide with add and mul as well: max == or and
> > min == and. The maxof/minof of that type is again trivial as well, and
> > arguably even more elegantly defined than on the other integer types
> > (because of the saturating behaviour of add, that maxof is the fixed-point
> > of the operation add1, and minof the fixed point of mul-any).
>
> I agree it would make perfect sense to define _Maxof and _Minof with
> bool. It is clear that _Maxof(bool)==true and _Minof(bool)==false;
> I don't think anyone would be surprised by that. However, I doubt the
> usefulness of that.
>
> Here are all the uses of these operators in the shadow utils project
> (of course, implemented as macros with the usual bit shifts):
>
> alx@devuan:~/src/shadow/shadow/master$ grep -rh -C2 'type_m' lib* src/
> | grep -v ^$
> #define str2i(T, ...) a2i(T, __VA_ARGS__, NULL, 0, type_min(T),
> type_max(T))
> #define str2sh(...) str2i(short, __VA_ARGS__)
> --
> get_gid(const char *restrict gidstr, gid_t *restrict gid)
> {
> return a2i(gid_t, gid, gidstr, NULL, 10, type_min(gid_t),
> type_max(gid_t));
> }
> --
> get_pid(const char *restrict pidstr, pid_t *restrict pid)
> {
> return a2i(pid_t, pid, pidstr, NULL, 10, 1, type_max(pid_t));
> }
> --
> get_uid(const char *restrict uidstr, uid_t *restrict uid)
> {
> return a2i(uid_t, uid, uidstr, NULL, 10, type_min(uid_t),
> type_max(uid_t));
> }
> --
> } else {
> if (a2i(rlim_t, &l, value, NULL, 10, 0,
> type_max(rlim_t)) == -1
> && errno != ENOTSUP)
> {
> --
> #define stype_max(T)
> \
> (
> \
> (T) (((((T) 1 << (WIDTHOF(T) - 2)) - 1) << 1) + 1)
> \
> )
> #define utype_max(T)
> \
> (
> \
> (T) -1
> \
> )
> #define type_max(T)
> \
> (
> \
> (T) (is_signed(T) ? stype_max(T) : utype_max(T))
> \
> )
> #define type_min(T)
> \
> (
> \
> (T) ~type_max(T)
> \
> )
> --
> const char *pos;
> struct id_range result = {
> .first = type_max(id_t),
> .last = type_min(id_t)
> };
> --
> static_assert(is_same_type(id_t, gid_t), "");
> first = type_min(id_t);
> last = type_max(id_t);
> if (a2i(id_t, &first, str, &pos, 10, first, last) == -1
>
> All of the uses are actually related to a2i() calls. a2i() is
> a type-generic macro wrapper around strtoi(3bsd) --which itself is a
> wrapper around strtoimax(3)--, which works for arbitrary (non-boolean)
> integer types.
>
> Another case where I would expect these macros to be useful is in the
> implementation of <stdbit.h> APIs. Do we want to support things like
> popcount((bool)1)? The answers are coupled, I think.
>
> For example:
>
> T
> bit_ceil(T x)
> {
> return 1 + (_Maxof(T) >> leading_zeros(x));
> }
And I don't think we want to support bool in <stdbit.h>. It doesn't
behave like all the other unsigned integer types:
alx@devuan:~/tmp$ cat bc.c
#include <stdbool.h>
#include <stdio.h>
#define bit_ceil_b(x) ((bool)1 + ((bool)1 >> (x == 0 ? 1 : 0)))
#define bit_ceil_u1(x) (1wbu + (1wbu >> (x == 0 ? 1 : 0)))
int
main(void)
{
bool b;
unsigned _BitInt(1) u;
b = 1;
u = 1;
printf("%d\n", (int) bit_ceil_b(b));
printf("%d\n", (int) bit_ceil_u1(u));
b = 0;
u = 0;
printf("%d\n", (int) bit_ceil_b(b));
printf("%d\n", (int) bit_ceil_u1(u));
}
alx@devuan:~/tmp$ gcc -Wall -Wextra bc.c
alx@devuan:~/tmp$ ./a.out
2
0
1
1
> > > Also, it's easy to extend features, but not so much to narrow them.
> > > Thus, I find it better (safer) to exclude it, at least initially. I
> > > welcome anyone interested in supporting bool to show a valid use case
> > > for it. I prefer to be cautious by default.
> >
> > Exceptions are the enemy of good language design. max/min on bool are
> > well defined as are maxof/minof. Excluding it from these operators seems
> > fairly unnatural. My 2 cents :-)
>
>
> Have a lovely day!
> Alex
>
> --
> <https://www.alejandro-colomar.es>
> Use port 80 (that is, <...:80/>).
--
<https://www.alejandro-colomar.es>
Use port 80 (that is, <...:80/>).
signature.asc
Description: PGP signature
