ptrdiff_t maximum

J

John Kelly

# include <stddef.h>
# include <stdio.h>

int
main (void)
{
ptrdiff_t const dx =
((ptrdiff_t) ~ ((ptrdiff_t) - 1 < 1 ? (-1 - (((ptrdiff_t) 1
<< (sizeof (ptrdiff_t) * 8 - 2)) - 1 + ((ptrdiff_t) 1
<< (sizeof (ptrdiff_t) * 8 - 2)))) : (ptrdiff_t) 0));

printf ("ptrdiff_t maximum %d\n", dx);

return 0;
}
 
I

Ian Collins

On 08/23/10 07:43 AM, John Kelly wrote:

If an implementation has ptrdiff_t, it'll have PTRDIFF_MIN and
PTRDIFF_MAX defined.
 
J

John Kelly

If an implementation has ptrdiff_t, it'll have PTRDIFF_MIN and
PTRDIFF_MAX defined.

Interix has ptrdiff_t but no PTRDIFF_MAX.

I grepped /usr/include and /opt/gcc.3.3. It's not there.

On Interix 3.5 we have the bare essentials:

/usr/include/limits.h:60:#define INT_MAX 2147483647
/usr/include/limits.h:61:#define UINT_MAX 0xffffffff

Blame it on Microsoft's lip service to UNIX interoperability.

(just kidding Geoff!)

It's not a bad tool once you learn your way around.
 
B

Ben Pfaff

Ian Collins said:
If an implementation has ptrdiff_t, it'll have PTRDIFF_MIN and
PTRDIFF_MAX defined.

All implementations, both C89 and C99, have ptrdiff_t, so the
"if" part doesn't make sense. But only C99 has PTRDIFF_MIN and
PTRDIFF_MAX.
 
I

Ian Collins

All implementations, both C89 and C99, have ptrdiff_t, so the
"if" part doesn't make sense. But only C99 has PTRDIFF_MIN and
PTRDIFF_MAX.

Ah, sorry I've become too used to using the one true C!
 
B

Ben Bacarisse

John Kelly said:
# include <stddef.h>
# include <stdio.h>

int
main (void)
{
ptrdiff_t const dx =
((ptrdiff_t) ~ ((ptrdiff_t) - 1 < 1 ? (-1 - (((ptrdiff_t) 1
<< (sizeof (ptrdiff_t) * 8 - 2)) - 1 + ((ptrdiff_t) 1
<< (sizeof (ptrdiff_t) * 8 - 2)))) : (ptrdiff_t) 0));

printf ("ptrdiff_t maximum %d\n", dx);

return 0;
}

This prints -1 on my machine.

ptrdiff_t is a signed type so there is no need for the conditional
expression.

Why subtract from -1 and then bit-wise negate? Surely the expression
you subtract is just as good? I.e.

((ptrdiff_t)1 << sizeof dx * CHAR_BIT - 2) - 1 +
((ptrdiff_t)1 << sizeof dx * CHAR_BIT - 2)

is just as good and avoids a problem on machines that have symmetric
positive and negative ranges.

This must be for C90 since C99 has PTRDIFF_MAX. In C90 the safest way
to print types for which there is no conversion specifier is with a
cast to the longest type of the correct "signedness":

printf("ptrdiff_t maximum %ld\n", (long)dx);

CHAR_BIT would be better than 8 and even so you can't be sure that all
sizeof dx * CHAR_BIT bit are value bits.
 
P

Peter Nilsson

John Kelly said:
# include <stddef.h>
# include <stdio.h>

int
main (void)
{
    ptrdiff_t const dx =
        ((ptrdiff_t) ~ ((ptrdiff_t) - 1 < 1 ? (-1 - (((ptrdiff_t) 1
                        << (sizeof (ptrdiff_t) * 8 - 2)) - 1 + ((ptrdiff_t) 1
                        << (sizeof (ptrdiff_t) * 8 - 2)))) : (ptrdiff_t) 0));

    printf ("ptrdiff_t maximum %d\n", dx);

    return 0;}

Under C90...

#include <stdio.h>
#include <stddef.h>

int main(void)
{
ptrdiff_t max, new;
for (max = 32767; (new = 2 * max + 1) > max; )
max = new;
printf("%ld\n", (long) max);
return 0;
}
 
J

John Kelly

Under C90...

#include <stdio.h>
#include <stddef.h>

int main(void)
{
ptrdiff_t max, new;
for (max = 32767; (new = 2 * max + 1) > max; )
max = new;
printf("%ld\n", (long) max);
return 0;
}

I like that.

The signed integer multiplication overflow will get Seebs dancing. ;-)
 
B

Ben Pfaff

Peter Nilsson said:
Under C90...

#include <stdio.h>
#include <stddef.h>

int main(void)
{
ptrdiff_t max, new;
for (max = 32767; (new = 2 * max + 1) > max; )
max = new;
printf("%ld\n", (long) max);
return 0;
}

Doesn't this make assumptions about the behavior of signed
integer overflow, which yields undefined behavior?
 
J

John Kelly

Doesn't this make assumptions about the behavior of signed
integer overflow, which yields undefined behavior?

Yes but ISTM you can (double) cast the intermediate result

for (max = 32767; (new = 2 * (double)max + 1) > max; )

to fix it up.
 
I

Ian Collins

# include<stddef.h>
# include<stdio.h>

int
main (void)
{
ptrdiff_t const dx =
((ptrdiff_t) ~ ((ptrdiff_t) - 1< 1 ? (-1 - (((ptrdiff_t) 1
<< (sizeof (ptrdiff_t) * 8 - 2)) - 1 + ((ptrdiff_t) 1
<< (sizeof (ptrdiff_t) * 8 - 2)))) : (ptrdiff_t) 0));

printf ("ptrdiff_t maximum %d\n", dx);

return 0;
}

Or:

#include <stdio.h>
#include <stddef.h>
#include <limits.h>

int main()
{
printf("ptrdiff_t maximum %ld\n",
(long)(~(1UL<<(sizeof(ptrdiff_t)*CHAR_BIT-1))));
}
 
J

John Kelly

Doesn't this make assumptions about the behavior of signed
integer overflow, which yields undefined behavior?

Yes, but here's a fix.

If somebody with a 64-bit machine would run this, and post the output I
would appreciate it.



# include <stdio.h>
# include <stddef.h>

int main(void) {

ptrdiff_t last, next;

for (last = 32767; (next = 2 * (double)last + 1) > last; ) {
printf ("last = %ld double = %f next = %ld\n", (long)last, 2 *
(double)last, (long)next);
last = next;

}
printf("%ld\n", (long) last);
return 0;
}
 
G

Geoff

Yes, but here's a fix.

If somebody with a 64-bit machine would run this, and post the output I
would appreciate it.



# include <stdio.h>
# include <stddef.h>

int main(void) {

ptrdiff_t last, next;

for (last = 32767; (next = 2 * (double)last + 1) > last; ) {
printf ("last = %ld double = %f next = %ld\n", (long)last, 2 *
(double)last, (long)next);
last = next;

}
printf("%ld\n", (long) last);
return 0;
}

last = 32767 double = 65534.000000 next = 65535
last = 65535 double = 131070.000000 next = 131071
last = 131071 double = 262142.000000 next = 262143
last = 262143 double = 524286.000000 next = 524287
last = 524287 double = 1048574.000000 next = 1048575
last = 1048575 double = 2097150.000000 next = 2097151
last = 2097151 double = 4194302.000000 next = 4194303
last = 4194303 double = 8388606.000000 next = 8388607
last = 8388607 double = 16777214.000000 next = 16777215
last = 16777215 double = 33554430.000000 next = 33554431
last = 33554431 double = 67108862.000000 next = 67108863
last = 67108863 double = 134217726.000000 next = 134217727
last = 134217727 double = 268435454.000000 next = 268435455
last = 268435455 double = 536870910.000000 next = 536870911
last = 536870911 double = 1073741822.000000 next = 1073741823
last = 1073741823 double = 2147483646.000000 next = 2147483647
last = 2147483647 double = 4294967294.000000 next = -1
last = -1 double = 8589934590.000000 next = -1
last = -1 double = 17179869182.000000 next = -1
last = -1 double = 34359738366.000000 next = -1
last = -1 double = 68719476734.000000 next = -1
last = -1 double = 137438953470.000000 next = -1
last = -1 double = 274877906942.000000 next = -1
last = -1 double = 549755813886.000000 next = -1
last = -1 double = 1099511627774.000000 next = -1
last = -1 double = 2199023255550.000000 next = -1
last = -1 double = 4398046511102.000000 next = -1
last = -1 double = 8796093022206.000000 next = -1
last = -1 double = 17592186044414.000000 next = -1
last = -1 double = 35184372088830.000000 next = -1
last = -1 double = 70368744177662.000000 next = -1
last = -1 double = 140737488355326.000000 next = -1
last = -1 double = 281474976710654.000000 next = -1
last = -1 double = 562949953421310.000000 next = -1
last = -1 double = 1125899906842622.000000 next = -1
last = -1 double = 2251799813685246.000000 next = -1
last = -1 double = 4503599627370494.000000 next = -1
last = -1 double = 9007199254740990.000000 next = -1
last = -1 double = 18014398509481982.000000 next = 0
last = 0 double = 36028797018963968.000000 next = 0
last = 0 double = 72057594037927936.000000 next = 0
last = 0 double = 144115188075855870.000000 next = 0
last = 0 double = 288230376151711740.000000 next = 0
last = 0 double = 576460752303423490.000000 next = 0
last = 0 double = 1152921504606847000.000000 next = 0
last = 0 double = 2305843009213694000.000000 next = 0
last = 0 double = 4611686018427387900.000000 next = 0
0
 
J

John Kelly

last = 0 double = 36028797018963968.000000 next = 0
last = 0 double = 72057594037927936.000000 next = 0
last = 0 double = 144115188075855870.000000 next = 0
last = 0 double = 288230376151711740.000000 next = 0
last = 0 double = 576460752303423490.000000 next = 0
last = 0 double = 1152921504606847000.000000 next = 0
last = 0 double = 2305843009213694000.000000 next = 0
last = 0 double = 4611686018427387900.000000 next = 0

looks like the printf needs long long, can you fix that and try again?
 
G

Geoff

I pasted and posted too quick. I think you wanted something like this:

# include <stdio.h>
# include <stddef.h>

int main(void) {

ptrdiff_t last, next;

for (last = 32767; (next = 2 * (double)last + 1) > last; ) {
printf ("last = %lld double = %f next = %lld\n",
(long long)last, 2 * (double)last, (long long)next);
last = next;

}
printf("%lld\n", (long long) last);
return 0;
}

With output like this:

last = 32767 double = 65534.000000 next = 65535
last = 65535 double = 131070.000000 next = 131071
last = 131071 double = 262142.000000 next = 262143
last = 262143 double = 524286.000000 next = 524287
last = 524287 double = 1048574.000000 next = 1048575
last = 1048575 double = 2097150.000000 next = 2097151
last = 2097151 double = 4194302.000000 next = 4194303
last = 4194303 double = 8388606.000000 next = 8388607
last = 8388607 double = 16777214.000000 next = 16777215
last = 16777215 double = 33554430.000000 next = 33554431
last = 33554431 double = 67108862.000000 next = 67108863
last = 67108863 double = 134217726.000000 next = 134217727
last = 134217727 double = 268435454.000000 next = 268435455
last = 268435455 double = 536870910.000000 next = 536870911
last = 536870911 double = 1073741822.000000 next = 1073741823
last = 1073741823 double = 2147483646.000000 next = 2147483647
last = 2147483647 double = 4294967294.000000 next = 4294967295
last = 4294967295 double = 8589934590.000000 next = 8589934591
last = 8589934591 double = 17179869182.000000 next = 17179869183
last = 17179869183 double = 34359738366.000000 next = 34359738367
last = 34359738367 double = 68719476734.000000 next = 68719476735
last = 68719476735 double = 137438953470.000000 next = 137438953471
last = 137438953471 double = 274877906942.000000 next = 274877906943
last = 274877906943 double = 549755813886.000000 next = 549755813887
last = 549755813887 double = 1099511627774.000000 next = 1099511627775
last = 1099511627775 double = 2199023255550.000000 next =
2199023255551
last = 2199023255551 double = 4398046511102.000000 next =
4398046511103
last = 4398046511103 double = 8796093022206.000000 next =
8796093022207
last = 8796093022207 double = 17592186044414.000000 next =
17592186044415
last = 17592186044415 double = 35184372088830.000000 next =
35184372088831
last = 35184372088831 double = 70368744177662.000000 next =
70368744177663
last = 70368744177663 double = 140737488355326.000000 next =
140737488355327
last = 140737488355327 double = 281474976710654.000000 next =
281474976710655
last = 281474976710655 double = 562949953421310.000000 next =
562949953421311
last = 562949953421311 double = 1125899906842622.000000 next =
1125899906842623
last = 1125899906842623 double = 2251799813685246.000000 next =
2251799813685247
last = 2251799813685247 double = 4503599627370494.000000 next =
4503599627370495
last = 4503599627370495 double = 9007199254740990.000000 next =
9007199254740991
last = 9007199254740991 double = 18014398509481982.000000 next =
18014398509481984
last = 18014398509481984 double = 36028797018963968.000000 next =
36028797018963968
last = 36028797018963968 double = 72057594037927936.000000 next =
72057594037927936
last = 72057594037927936 double = 144115188075855870.000000 next =
144115188075855872
last = 144115188075855872 double = 288230376151711740.000000 next =
288230376151711744
last = 288230376151711744 double = 576460752303423490.000000 next =
576460752303423488
last = 576460752303423488 double = 1152921504606847000.000000 next =
1152921504606846976
last = 1152921504606846976 double = 2305843009213694000.000000 next =
2305843009213693952
last = 2305843009213693952 double = 4611686018427387900.000000 next =
4611686018427387904
4611686018427387904
 
F

Francesco S. Carta

Yes, but here's a fix.

If somebody with a 64-bit machine would run this, and post the output I
would appreciate it.



# include<stdio.h>
# include<stddef.h>

int main(void) {

ptrdiff_t last, next;

for (last = 32767; (next = 2 * (double)last + 1)> last; ) {
printf ("last = %ld double = %f next = %ld\n", (long)last, 2 *
(double)last, (long)next);
last = next;

}
printf("%ld\n", (long) last);
return 0;
}

Caveat: I have not even the slightest idea whether these results are
relevant or not, I only know that I have a 64-bit machine.

MinGW 4.4.0, Windows7, AMD Athlon(tm) II Dual-Core M300 2.00 Ghz

last = 32767 double = 65534.000000 next = 65535
last = 65535 double = 131070.000000 next = 131071
last = 131071 double = 262142.000000 next = 262143
last = 262143 double = 524286.000000 next = 524287
last = 524287 double = 1048574.000000 next = 1048575
last = 1048575 double = 2097150.000000 next = 2097151
last = 2097151 double = 4194302.000000 next = 4194303
last = 4194303 double = 8388606.000000 next = 8388607
last = 8388607 double = 16777214.000000 next = 16777215
last = 16777215 double = 33554430.000000 next = 33554431
last = 33554431 double = 67108862.000000 next = 67108863
last = 67108863 double = 134217726.000000 next = 134217727
last = 134217727 double = 268435454.000000 next = 268435455
last = 268435455 double = 536870910.000000 next = 536870911
last = 536870911 double = 1073741822.000000 next = 1073741823
last = 1073741823 double = 2147483646.000000 next = 2147483647
2147483647
 
G

Geoff

This prints -1 on my machine.

ptrdiff_t is a signed type so there is no need for the conditional
expression.

Why subtract from -1 and then bit-wise negate? Surely the expression
you subtract is just as good? I.e.

((ptrdiff_t)1 << sizeof dx * CHAR_BIT - 2) - 1 +
((ptrdiff_t)1 << sizeof dx * CHAR_BIT - 2)

is just as good and avoids a problem on machines that have symmetric
positive and negative ranges.

This must be for C90 since C99 has PTRDIFF_MAX. In C90 the safest way
to print types for which there is no conversion specifier is with a
cast to the longest type of the correct "signedness":

printf("ptrdiff_t maximum %ld\n", (long)dx);

CHAR_BIT would be better than 8 and even so you can't be sure that all
sizeof dx * CHAR_BIT bit are value bits.

On a Win7 box running an i7 and VS 2010 Pro:

# include <stddef.h>
# include <stdio.h>
# include <limits.h>

int
main (void)
{
ptrdiff_t const dx =
((ptrdiff_t)1 << (sizeof dx * CHAR_BIT - 2)) - 1 +
((ptrdiff_t)1 << (sizeof dx * CHAR_BIT - 2));

printf ("ptrdiff_t maximum %llx = %lld\n", dx, dx);
printf ("ptrdiff_t minimum %llx = %lld\n", -dx - 1, -dx - 1);

return 0;
}

----------------------------

Output:

ptrdiff_t maximum 7fffffffffffffff = 9223372036854775807
ptrdiff_t minimum 8000000000000000 = -9223372036854775808
 
F

Francesco S. Carta

On a Win7 box running an i7 and VS 2010 Pro:

# include<stddef.h>
# include<stdio.h>
# include<limits.h>

int
main (void)
{
ptrdiff_t const dx =
((ptrdiff_t)1<< (sizeof dx * CHAR_BIT - 2)) - 1 +
((ptrdiff_t)1<< (sizeof dx * CHAR_BIT - 2));

printf ("ptrdiff_t maximum %llx = %lld\n", dx, dx);
printf ("ptrdiff_t minimum %llx = %lld\n", -dx - 1, -dx - 1);

return 0;
}

----------------------------

Output:

ptrdiff_t maximum 7fffffffffffffff = 9223372036854775807
ptrdiff_t minimum 8000000000000000 = -9223372036854775808


The last code above on:
MinGW 4.4.0, Windows7, AMD Athlon(tm) II Dual-Core M300 2.00 Ghz

Gives:
ptrdiff_t maximum 7fffffff7fffffff = 8541177558308426082
ptrdiff_t minimum 8000000080000000 = 8541177558308426082
 
F

Francesco S. Carta

The last code above on:
MinGW 4.4.0, Windows7, AMD Athlon(tm) II Dual-Core M300 2.00 Ghz

Gives:
ptrdiff_t maximum 7fffffff7fffffff = 8541177558308426082
ptrdiff_t minimum 8000000080000000 = 8541177558308426082

Are these (and the others from me, elsethread) results meaningful?

If not I'll just avoid posting them - I did report them because they
seem weird at best.
 
J

John Kelly

Are these (and the others from me, elsethread) results meaningful?

If not I'll just avoid posting them - I did report them because they
seem weird at best.

I don't know much about MinGW, but it's good to have a variety of data.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top