From: John Allen (no email)
Date: Tue Sep 02 2003 - 02:46:38 EDT
On Tuesday 02 September 2003 01:41, Wietse Venema wrote:
> 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.
>
I added a printf("0x%llx\n", MAXINT(long long));
before the off_t, on my Athlon box, and I get.
0x7f
0x7fff
0x7fffffff
0x7fffffff
0x7fffffffffffffff
0x7fffffff7fffffff
Note the weird off_t value. Its like is has been treated as 2 longs stuck together.
Linux nine 2.4.22-1mdk #1 Mon Aug 25 11:19:10 EDT 2003 i686 unknown unknown GNU/Linux
> 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
-- John Allen, Email: mailto: MandrakeClub Silver Member.
|
|
|