Implicit assumptions (was: Re: Some fun with -O2)
Walter von Entferndt
walter.von.entferndt at posteo.net
Thu Jan 14 22:08:16 UTC 2021
At Donnerstag, 14. Januar 2021, 20:00:31 CET, Mark Millard wrote:
> Not on FreeBSD for 32-bit powerpc it is not: time_t
> is 64 bits wide there but long int is not:
>
> From /usr/include/machine/_types.h :
>
> typedef __int64_t __time_t; /* time()... */
>
> From /usr/include/sys/types.h :
>
> typedef __time_t time_t;
>
Ha! Thx... Ok, then we have to use the *sizeof* operator and if you thought
there's one holy constant in computer science - that a byte has 8 bits, and we
can use that as an ... /implicit assumption/ ... - you might be surprised that
it's declared explicitely in
sys/param.h:#define NBBY 8 /* number of bits in a byte */
and you can find the number 8 (and 16, 24, 32, 48,...) all over other header
files without using that definition (NBBY) so these are strictly speaking all
wrong... ;) So now we have (errorneous!)
[delete #include <limits.h>]
#include <sys/param.h>
time_t time_t_max;
...
for (i = time_t_max = 1; i < NBBY*sizeof time_t_max; i++)
time_t_max *= 2;
time_t_max--;
which gives the intended result but is strictly speaking wrong, because it you
don't do the decrement, the value is negative, and the decrement of a negative
number should be negative, too. I.e. this only gives what we want because we
make use of an undefined behaviour. So let's do better (and portable):
#include <sys/param.h>
signed_t signed_max, t1;
for (int i = signed_max = 1; i < NBBY*sizeof signed_max - 1; i++) {
signed_max *= 2; // eq: signed_max <<= 1;
t1 = signed_max - 1;
}
signed_max += t1; // eq: signed_max |= t1;
/* QED
* hopefully the compiler optimizes *=2 and we're using binary numbers ;)
*/
--
=|o) "Stell' Dir vor es geht und keiner kriegt's hin." (Wolfgang Neuss)
More information about the freebsd-hackers
mailing list