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