From: Wietse Venema (no email)
Date: Mon Sep 01 2003 - 20:41:36 EDT
Following up to my own posting, perhaps we have a portable
solution after all.
Wietse Venema:
> Postfix must be able to seek files, therefore files can't be larger
> than the largest off_t value. What should Postfix do when the
> system imposed file size limit is larger than what can be represented
> as a file offset? The best is to truncate the limit to the largest
> positive off_t value.
>
> It seems relatively safe to assume that off_t is a signed integer
> type in two's complement format. What is the portable way to find
> out the largest value of such a signed integer?
>
> Coming back to your proposed macro:
>
> #define FSIZE_MAX (off_t)1<<((sizeof(off_t)*8)-1)
>
> This macro assumes that bytes are 8 bits wide, but the C standard
> does not require this. Postfix runs on machines other than peecees
> and I would not like to lose those platforms. Fortunately, ANSI C
> defines the CHAR_BIT constant in <limits.h> for this exact purpose.
>
> So let's fix this portability problem. While we're at it, let's
> also fix a potential operator precedence problem by adding add
> outer parentheses. And let's generalize this macro a bit so that
> it can be tested easily.
>
> #define MAX_POSITIVE_OF(T) ((T) 1 << ((sizeof(T) * CHAR_BIT) - 1))
>
> This reveals that the original macro has bigger problems than 8-bit
> byte assumptions or operator precedence conflicts. The macro simply
> computes the wrong result.
>
> For example,
>
> MAX_POSITIVE_OF(char) evaluates to 128, should be 127
> MAX_POSITIVE_OF(short) evaluates to 32768, should be 32767
Here's something that appears to work better:
#include <sys/types.h>
#include <limits.h>
#include <stdio.h>
#define MAXINT(T) ((T) (((T)1 << ((sizeof(T) * CHAR_BIT) - 1) ^ ((T) -1))))
main()
{
printf("%d\n", MAXINT(char));
printf("%d\n", MAXINT(short));
printf("%d\n", MAXINT(int));
printf("%ld\n", MAXINT(long));
printf("%lld\n", MAXINT(off_t));
}
On my I386 box the output from this test program is:
127
32767
2147483647
2147483647
9223372036854775807
When changed to print hexadecimal output:
#include <sys/types.h>
#include <limits.h>
#include <stdio.h>
#define MAXINT(T) ((T) (((T)1 << ((sizeof(T) * CHAR_BIT) - 1) ^ ((T) -1))))
main()
{
printf("0x%x\n", MAXINT(char));
printf("0x%x\n", MAXINT(short));
printf("0x%x\n", MAXINT(int));
printf("0x%lx\n", MAXINT(long));
printf("0x%llx\n", MAXINT(off_t));
}
Output becomes:
0x7f
0x7fff
0x7fffffff
0x7fffffff
0x7fffffffffffffff
It would be nice to hear how this works on 64-bit systems. I can
try this on SPARC/Solaris myself.
Up to this point I think I understand how and why the macro works.
However, if someone can explain to me why this produces 0xffffffff
for long long on I386, then I am all ears. Every day brings an
opportunity to learn something new about the C programming language.
Wietse
|
|
|