468,463 Members | 1,910 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,463 developers. It's quick & easy.

Direct computation of integer limits in K&R2?

Hello all,

In K&R2 one exercise asks the reader to compute and print the limits for
the basic integer types. This is trivial for unsigned types. But is it
possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.

Mar 11 '08
88 3265
santosh wrote:
Ioannis Vranos wrote:
>Ioannis Vranos wrote:
>>Translated:

Exercise 2-1. Write a program to determine the value ranges of the
variable types char, short, int, and long, both for signed and the
unsigned ones, displaying the appropriate values from the standard
headers, and by direct calculation. And something more difficult, if
you attempt to calculate it: determine the value ranges of the
various floating-point types.

I think as it is spelled above we can get some flexibility. I think by
displaying the integer min and max values from limits.h, we can use
this information to determine how these types are implemented.

What do you think?

Perhaps, but that's a bit of a cheat, IMO.

In any case how do you propose to use the min. and max. values in
limits.h to work out the integer representation?

Well we can see if INT_MIN==-INT_MAX-1 or not. And then use my code if
this is the case, for the else part perhaps you may provide some
solution. :-)

Mar 13 '08 #51
Richard Heathfield wrote:
CBFalconer said:
>Ben Bacarisse wrote:
>>Kaz Kylheku <kk******@gmail.comwrites:
... snip ...
>>>
This means that the sign bit is quite impervious to bit
manipulation.

It must participate in other bit operations, though, like ~, &,
| and ^. Even so,I can't see any way to avoid UB when trying to
calculate the range of int. Equally, I don't have a persuasive
argument that it *can't* be done, either.

Totally unnecessary. All those integral max values are specified
in <limits.h>. That's why.

Is it, then, your claim that doing K&R exercises is a waste of time?
I believe (K&R is lost in the mess) the original problem didn't ban
limits.h

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Mar 14 '08 #52
Ioannis Vranos wrote:
>
.... snip ...
>
What is N869? My answer as C95 based. Actually since it is an
exercise of K&R2, it is a C90 question.
It is the last draft of C99 before publication, and the last
version available in text form. You can get one organized for
quoting, grepping, etc. bzip2 compressed at:

<http://cbfalconer.home.att.net/download/n869_txt.bz2>

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Mar 14 '08 #53
Ioannis Vranos wrote:
user923005 wrote:
>>Can you mention the chapter of K&R2 where this exercise is?

Exercise 2.1, page 36

I have not the English text but a local-language translated book,
so I translate the exercise in English here (if anyone can post
the English version of this K&R2 exercise, it will be great):

Translated:

Exercise 2-1. Write a program to determine the value ranges of the
variable types char, short, int, and long, both for signed and the
unsigned ones, displaying the appropriate values from the standard
headers, and by direct calculation. And something more difficult,
if you attempt to calculate it: determine the value ranges of the
various floating-point types.
Basically, just #include <limits.h>. Other for floats.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Mar 14 '08 #54
CBFalconer <cb********@yahoo.comwrites:
Richard Heathfield wrote:
>CBFalconer said:
<snip>
>>Totally unnecessary. All those integral max values are specified
in <limits.h>. That's why.

Is it, then, your claim that doing K&R exercises is a waste of time?

I believe (K&R is lost in the mess) the original problem didn't ban
limits.h
No, but it suggests trying to do it by direct calculation as well. It
is from that suggestion that the whole thread grew.

--
Ben.
Mar 14 '08 #55
CBFalconer <cbfalco...@yahoo.comwrote:
Ark Khasin wrote:
Peter Nilsson wrote:
Unfortunately, many implementations are somewhat
inconsistent. Consider...
>
* #include <limits.h>
* #include <stdio.h>
>
* int main(void) {
* * printf("ULONG_MAX = %lu\n", ULONG_MAX);
>
* #if -1 == -1ul
* * puts("-1 == -1ul [pre]");
* #endif
>
* * if (-1 == -1ul)
* * * puts("-1 == -1ul");
>
* #if 4294967295 == -1ul
* * puts("4294967295 == -1ul [pre]");
* #endif
>
* * if (4294967295 == -1ul)
* * * puts("4294967295 == -1ul");
* * return 0;
* }
>
The output for me using delorie gcc 4.2.1 with -ansi
-pedantic is...
>
* ULONG_MAX = 4294967295
* -1 == -1ul [pre]
* -1 == -1ul
* 4294967295 == -1ul
>
As you can see, there is a discrepancy between the way
that preprocessor arithmetic is evaluated. Fact is,
gcc is not the only compiler to show problems.

What's wrong with that,
It violates the standard in the cited section that you
snipped...

C89 draft 3.8.1
...The resulting tokens comprise the controlling constant
expression which is evaluated according to the rules of
$3.4 using arithmetic that has at least the ranges
specified in $2.2.4.2, except that int and unsigned int
act as if they have the same representation as,
respectively, long and unsigned long. ...

The output should have included...

4294967295 == -1ul [pre]
remembering that (for gcc, on xx86's) a
long is defined to be identical to an int.
They're not compatible types, but if you mean they
have the same representation then I don't see how
that's relevant.

--
Peter
Mar 14 '08 #56
santosh wrote:
Hello all,

In K&R2 one exercise asks the reader to compute and print the limits for
the basic integer types. This is trivial for unsigned types. But is it
possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.

C90:

The original exercise text as provided by Richard Heathfield is:

Exercise 2-1. Write a program to determine the ranges of char, short,
int, and long, both signed and unsigned, by printing appropriate values
from standard headers and by direct computation. Harder if you compute
them: determine the ranges of the various floating-point types.
Any ideas?
I think the text gives us space, in the signed int case to see if
INT_MIN== -INT_MAX-1 or INT_MIN== -INT_MAX, and act accordingly with
unsigned int:
#include <stdio.h>
#include <limits.h>
int main()
{
unsigned x= -1;

int INTMIN, INTMAX;

printf("INT_MIN= %d, INT_MAX= %d\n", INT_MIN, INT_MAX);

if (INT_MIN== -INT_MAX -1)
{
INTMAX=x /2;

INTMIN= -INTMAX -1;
}

else
{
INTMAX=x /2;

INTMIN= -INTMAX;

}
printf("INTMIN= %d, INTMAX= %d\n", INTMIN, INTMAX);
return 0;
}

Probably this is a stupid solution. But what can we take for granted,
"by printing appropriate values from standard headers"?
Mar 14 '08 #57
On Mar 13, 6:51*pm, Ioannis Vranos <ivra...@nospam.no.spamfreemail.gr>
wrote:
santosh wrote:
Hello all,
In K&R2 one exercise asks the reader to compute and print the limits for
the basic integer types. This is trivial for unsigned types. But is it
possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.

C90:

The original exercise text as provided by Richard Heathfield is:

Exercise 2-1. Write a program to determine the ranges of char, short,
int, and long, both signed and unsigned, by printing appropriate values
from standard headers and by direct computation. Harder if you compute
them: determine the ranges of the various floating-point types.

Any ideas?

I think the text gives us space, in the signed int case to see if
INT_MIN== -INT_MAX-1 or INT_MIN== -INT_MAX, and act accordingly with
unsigned int:

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

int main()
{
* * *unsigned x= -1;

* * *int INTMIN, INTMAX;

* * *printf("INT_MIN= %d, INT_MAX= %d\n", INT_MIN, INT_MAX);

* * *if (INT_MIN== -INT_MAX -1)
* * *{
* * * * * * INTMAX=x /2;

* * * * * * INTMIN= -INTMAX -1;
* * *}

* * *else
* * *{
* * * * * * INTMAX=x /2;

* * * * * * INTMIN= -INTMAX;

* * *}

* * *printf("INTMIN= %d, INTMAX= %d\n", INTMIN, INTMAX);

* * *return 0;

}

Probably this is a stupid solution. But what can we take for granted,
"by printing appropriate values from standard headers"?
This probably works on many platforms, but a really interesting
solution would be one that works on every platform.
Mar 14 '08 #58
On Mar 13, 8:51 pm, Ioannis Vranos <ivra...@nospam.no.spamfreemail.gr>
wrote:
santosh wrote:
Hello all,
In K&R2 one exercise asks the reader to compute and print the limits for
the basic integer types. This is trivial for unsigned types. But is it
possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.

C90:

The original exercise text as provided by Richard Heathfield is:

Exercise 2-1. Write a program to determine the ranges of char, short,
int, and long, both signed and unsigned, by printing appropriate values
from standard headers and by direct computation. Harder if you compute
them: determine the ranges of the various floating-point types.

Any ideas?

I think the text gives us space, in the signed int case to see if
INT_MIN== -INT_MAX-1 or INT_MIN== -INT_MAX, and act accordingly with
unsigned int:

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

int main()
{
unsigned x= -1;

int INTMIN, INTMAX;

printf("INT_MIN= %d, INT_MAX= %d\n", INT_MIN, INT_MAX);

if (INT_MIN== -INT_MAX -1)
{
INTMAX=x /2;

INTMIN= -INTMAX -1;
}

else
{
INTMAX=x /2;

INTMIN= -INTMAX;

}

printf("INTMIN= %d, INTMAX= %d\n", INTMIN, INTMAX);

return 0;

}

Probably this is a stupid solution. But what can we take for granted,
"by printing appropriate values from standard headers"?
What did you do in this code? Did you compute INT_MAX and
INT_MIN using INT_MAX and INT_MIN? Note that (unsigned)-1 / 2
may be out of range of int (by the way, C99 rationale says
that the committee was told that there actually was an
implementation where UINT_MAX + 1 was *four* times INT_MAX + 1).

Yevgen
Mar 14 '08 #59
Ioannis Vranos said:

<snip>
The original exercise text as provided by Richard Heathfield is:

Exercise 2-1. Write a program...
Just a nit. It was Brian Kernighan who originally wrote that exercise, not
me. I only quoted it!

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Mar 14 '08 #60
CBFalconer said:
Ioannis Vranos wrote:
>>
... snip ...
>>
What is N869? My answer as C95 based. Actually since it is an
exercise of K&R2, it is a C90 question.

It is the last draft of C99 before publication, and the last
version available in text form.
He doesn't want one. In case you hadn't noticed, he's teaching a C90/C95
course.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Mar 14 '08 #61
Displaying the limits using the macros is easy: the C89 Standard mandates
that the macros in <limits.hmust have the same type as an expression
that is an object of the corresponding type converted according to the
integral promotions (this excludes CHAR_BIT and MB_LEN_MAX). So this is
perfectly reasonable:

printf("char signed min = %d\n", SCHAR_MIN);
printf("signed int min = %d\n", INT_MIN);
printf("signed int max = %d\n", INT_MAX);
/* etc. */

For calculating them, Tondo & Gimpel suggest this in "The C Answer Book":

printf("signed char min = %d\n", ~(char)((unsigned char) ~0 >1));
printf("signed char max = %d\n", (char)((unsigned char) ~0 >1));
printf("unsigned short min = %d\n", ~(short)((unsigned short) ~0 >1));
printf("unsigned short max = %d\n", (short)((unsigned short) ~0 >1));

and so on.

Obviously, I don't know to what peer review T&G's Answer Book was subject,
but if their solutions are not correct, I would like to know.

--
Martin

Mar 14 '08 #62
ym******@gmail.com wrote:
What did you do in this code? Did you compute INT_MAX and
INT_MIN using INT_MAX and INT_MIN? Note that (unsigned)-1 / 2
may be out of range of int (by the way, C99 rationale says
that the committee was told that there actually was an
implementation where UINT_MAX + 1 was *four* times INT_MAX + 1).

How can this happen given that sizeof(int)== sizeof(unsigned it)?
Mar 14 '08 #63
Ioannis Vranos <iv*****@nospam.no.spamfreemail.grwrites:
ym******@gmail.com wrote:
>What did you do in this code? Did you compute INT_MAX and
INT_MIN using INT_MAX and INT_MIN? Note that (unsigned)-1 / 2
may be out of range of int (by the way, C99 rationale says
that the committee was told that there actually was an
implementation where UINT_MAX + 1 was *four* times INT_MAX + 1).


How can this happen given that sizeof(int)== sizeof(unsigned it)?
Not all the bits in int are required to be value or sign bits (some
may be padding bits). And some of the bits that are value bits in an
unsigned int are allowed to be padding bits in the signed int.

--
Micah J. Cowan
Programmer, musician, typesetting enthusiast, gamer...
http://micah.cowan.name/
Mar 14 '08 #64
Ioannis Vranos wrote:
>
.... snip ...
>
Well we can see if INT_MIN==-INT_MAX-1 or not. And then use my
code if this is the case, for the else part perhaps you may
provide some solution. :-)
If not, you have discovered undefined behaviour.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
--
Posted via a free Usenet account from http://www.teranews.com

Mar 14 '08 #65
Martin <m@b.cwrites:
Displaying the limits using the macros is easy:
Agreed, so I've snipped...
For calculating them, Tondo & Gimpel suggest this in "The C Answer Book":

printf("signed char min = %d\n", ~(char)((unsigned char) ~0 >1));
printf("signed char max = %d\n", (char)((unsigned char) ~0 >1));
printf("unsigned short min = %d\n", ~(short)((unsigned short) ~0 >1));
printf("unsigned short max = %d\n", (short)((unsigned short) ~0 >1));

and so on.

Obviously, I don't know to what peer review T&G's Answer Book was
subject, but if their solutions are not correct, I would like to
know.
These can't work on sign & magnitude systems since the min. and max.
values aren't the (bit-wise) complement of each other. On ones'
complement systems, (unsigned char)~0 should be zero, I think -- the
conversion is based on the value of ~0 not the bit pattern. On twos'
complement systems, it is possible that both signed and unsigned short
have the same number of value bits. On such a system, the expression
will print too small a maximum.

--
Ben.
Mar 14 '08 #66
On Tue, 11 Mar 2008 23:41:33 -0500, CBFalconer wrote:
Harald van D?k wrote:
>santosh wrote:
>>In K&R2 one exercise asks the reader to compute and print the limits
for the basic integer types. This is trivial for unsigned types. But
is it possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.

#include <stdio.h>
int main(void) {
unsigned u = -1;
int i;
while ((i = u) < 0 || i != u)
u = u >1;
printf("INT_MAX == %u\n", u);
}

This is not guaranteed to work in C99, where the conversion of an
out-of- range integer may raise a signal, but it's valid C90, since the
result of the conversion must be a valid int, and therefore between
INT_MIN and INT_MAX.

This CAN'T work everywhere.
Yes, it can.
The u = -1 statement is legal, and results
in UINT_MAX value. However the first i = u statement always overruns
the INT_MAX value for i, unless the system has INT_MAX defined to be
equal to UINT_MAX. Very rare. So the result of that statement is
implementation defined.
Of course. And any of the permissible implementation-defined values of i
will result in the intended behaviour.

As long as u INT_MAX, then i cannot possibly be equal to u. It could be
negative, or it could be zero, or it could be positive. If it is
negative, then the comparison to 0 continues the loop. If it is not
negative, then i != u, because i <= INT_MAX, and u INT_MAX, so the loop
continues.

As soon as u <= INT_MAX, then i must be equal to u, so the loop exits.
Mar 14 '08 #67
On Fri, 14 Mar 2008 03:51:29 +0200, Ioannis Vranos wrote:
if (INT_MIN== -INT_MAX -1)
On systems where the condition doesn't hold, -INT_MAX -1 overflows.
Mar 14 '08 #68
Micah Cowan wrote:
Ioannis Vranos <iv*****@nospam.no.spamfreemail.grwrites:
>ym******@gmail.com wrote:
>>What did you do in this code? Did you compute INT_MAX and
INT_MIN using INT_MAX and INT_MIN? Note that (unsigned)-1 / 2
may be out of range of int (by the way, C99 rationale says
that the committee was told that there actually was an
implementation where UINT_MAX + 1 was *four* times INT_MAX + 1).

How can this happen given that sizeof(int)== sizeof(unsigned it)?

Not all the bits in int are required to be value or sign bits (some
may be padding bits). And some of the bits that are value bits in an
unsigned int are allowed to be padding bits in the signed int.
OK it is allowed, but is there any existing system where the value
ranges of signed int and unsigned int are different?
Mar 14 '08 #69
Ioannis Vranos wrote:
Micah Cowan wrote:
>Ioannis Vranos <iv*****@nospam.no.spamfreemail.grwrites:
>>ym******@gmail.com wrote:
What did you do in this code? Did you compute INT_MAX and
INT_MIN using INT_MAX and INT_MIN? Note that (unsigned)-1 / 2
may be out of range of int (by the way, C99 rationale says
that the committee was told that there actually was an
implementation where UINT_MAX + 1 was *four* times INT_MAX + 1).

How can this happen given that sizeof(int)== sizeof(unsigned it)?

Not all the bits in int are required to be value or sign bits (some
may be padding bits). And some of the bits that are value bits in an
unsigned int are allowed to be padding bits in the signed int.

OK it is allowed, but is there any existing system where the value
ranges of signed int and unsigned int are different?

With "value ranges" above I mean the total values of each type.
Mar 14 '08 #70
On Mar 14, 5:59*am, Martin <m...@b.cwrote:
Displaying the limits using the macros is easy: the C89 Standard mandates *
that the macros in <limits.hmust have the same type as an expression *
that is an object of the corresponding type converted according to the *
integral promotions (this excludes CHAR_BIT and MB_LEN_MAX). So this is *
perfectly reasonable:

* * printf("char signed min = %d\n", SCHAR_MIN);
* * printf("signed int min *= %d\n", INT_MIN);
* * printf("signed int max *= %d\n", INT_MAX);
* * /* etc. */

For calculating them, Tondo & Gimpel suggest this in "The C Answer Book":

* * printf("signed char min * *= %d\n", ~(char)((unsigned char) ~0 >1));
* * printf("signed char max * *= %d\n", *(char)((unsigned char) ~0 >1));
* * printf("unsigned short min = %d\n", ~(short)((unsigned short) ~0>1));
* * printf("unsigned short max = %d\n", *(short)((unsigned short) ~0 >1));

and so on.

Obviously, I don't know to what peer review T&G's Answer Book was subject,*
but if their solutions are not correct, I would like to know.
It works for two's complement. Maybe that's just the trick:
You have to write a different solution for each possible number
format.
Mar 14 '08 #71
user923005 wrote:
On Mar 14, 5:59*am, Martin <m...@b.cwrote:
>Displaying the limits using the macros is easy: the C89 Standard
mandates that the macros in <limits.hmust have the same type as an
expression that is an object of the corresponding type converted
according to the integral promotions (this excludes CHAR_BIT and
MB_LEN_MAX). So this is perfectly reasonable:

printf("char signed min = %d\n", SCHAR_MIN);
printf("signed int min *= %d\n", INT_MIN);
printf("signed int max *= %d\n", INT_MAX);
/* etc. */

For calculating them, Tondo & Gimpel suggest this in "The C Answer
Book":

printf("signed char min * *= %d\n", ~(char)((unsigned char) ~0 >>
1)); printf("signed char max * *= %d\n", *(char)((unsigned char) ~0
>1)); printf("unsigned short min = %d\n", ~(short)((unsigned short)
~0 >1)); printf("unsigned short max = %d\n", *(short)((unsigned
short) ~0 >1));

and so on.

Obviously, I don't know to what peer review T&G's Answer Book was
subject, but if their solutions are not correct, I would like to
know.

It works for two's complement. Maybe that's just the trick:
You have to write a different solution for each possible number
format.
The question doesn't mention the word "portable" at all anywhere, so I
guess that a machine specific answer will count as a solution too.

Mar 14 '08 #72
On Mar 14, 1:43 pm, Ioannis Vranos <ivra...@nospam.no.spamfreemail.gr>
wrote:
Micah Cowan wrote:
Ioannis Vranos <ivra...@nospam.no.spamfreemail.grwrites:
ymunt...@gmail.com wrote:
What did you do in this code? Did you compute INT_MAX and
INT_MIN using INT_MAX and INT_MIN? Note that (unsigned)-1 / 2
may be out of range of int (by the way, C99 rationale says
that the committee was told that there actually was an
implementation where UINT_MAX + 1 was *four* times INT_MAX + 1).
How can this happen given that sizeof(int)== sizeof(unsigned it)?
Not all the bits in int are required to be value or sign bits (some
may be padding bits). And some of the bits that are value bits in an
unsigned int are allowed to be padding bits in the signed int.

OK it is allowed, but is there any existing system where the value
ranges of signed int and unsigned int are different?
See above. You decide whether C rationale is lying or C committee
was lied to. I have no idea :)

Yevgen
Mar 14 '08 #73
On Mar 14, 1:58 pm, santosh <santosh....@gmail.comwrote:
user923005 wrote:
On Mar 14, 5:59 am, Martin <m...@b.cwrote:
Displaying the limits using the macros is easy: the C89 Standard
mandates that the macros in <limits.hmust have the same type as an
expression that is an object of the corresponding type converted
according to the integral promotions (this excludes CHAR_BIT and
MB_LEN_MAX). So this is perfectly reasonable:
printf("char signed min = %d\n", SCHAR_MIN);
printf("signed int min = %d\n", INT_MIN);
printf("signed int max = %d\n", INT_MAX);
/* etc. */
For calculating them, Tondo & Gimpel suggest this in "The C Answer
Book":
printf("signed char min = %d\n", ~(char)((unsigned char) ~0 >>
1)); printf("signed char max = %d\n", (char)((unsigned char) ~0
1)); printf("unsigned short min = %d\n", ~(short)((unsigned short)
~0 >1)); printf("unsigned short max = %d\n", (short)((unsigned
short) ~0 >1));
and so on.
Obviously, I don't know to what peer review T&G's Answer Book was
subject, but if their solutions are not correct, I would like to
know.
It works for two's complement. Maybe that's just the trick:
You have to write a different solution for each possible number
format.

The question doesn't mention the word "portable" at all anywhere, so I
guess that a machine specific answer will count as a solution too.
But then the following is a solution too:

int intmax = 2147483647;
int intmin = -2147483647 - 1;

Or, for "quite portable" version, look at glibc's limits.h.
And of course SCHAR_MAX = 127 :)

Yevgen
Mar 14 '08 #74
Ioannis Vranos wrote:
>
.... snip ...
>
OK it is allowed, but is there any existing system where the value
ranges of signed int and unsigned int are different?
Yes. Consider a 16 bit system. INT_MAX is 32767. INT_MIN is
-32768 (or -32767). UINT_MAX is 65536 (UINT_MIN is naturally 0).
It is allowable to reserve the value that would represent -32768 to
indicate a special condition, such as uninitialized. Or, for a 1's
complement machine, the bit pattern for -0 is forbidden.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Mar 14 '08 #75
Harald van D?k wrote:
CBFalconer wrote:
>Harald van D?k wrote:
.... snip ...
>>
>>#include <stdio.h>
int main(void) {
unsigned u = -1;
int i;
while ((i = u) < 0 || i != u)
u = u >1;
printf("INT_MAX == %u\n", u);
}

This is not guaranteed to work in C99, where the conversion of
an out-of- range integer may raise a signal, but it's valid C90,
since the result of the conversion must be a valid int, and
therefore between INT_MIN and INT_MAX.

This CAN'T work everywhere.

Yes, it can.
>The u = -1 statement is legal, and results in UINT_MAX value.
However the first i = u statement always overruns the INT_MAX
value for i, unless the system has INT_MAX defined to be equal
to UINT_MAX. Very rare. So the result of that statement is
implementation defined.

Of course. And any of the permissible implementation-defined
values of i will result in the intended behaviour.
I think you have a misinterpretation of 'implementaion-defined'.
This means that the action, on a particular implementation, is
defined. However that may well be "*** ABORT in line nnn, integer
overflow ***".

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Mar 14 '08 #76
On Fri, 14 Mar 2008 14:08:48 -0500, CBFalconer wrote:
Harald van D?k wrote:
>CBFalconer wrote:
>>Harald van D?k wrote:
... snip ...
>>>
#include <stdio.h>
int main(void) {
unsigned u = -1;
int i;
while ((i = u) < 0 || i != u)
u = u >1;
printf("INT_MAX == %u\n", u);
}

This is not guaranteed to work in C99, where the conversion of an
out-of- range integer may raise a signal, but it's valid C90, since
the result of the conversion must be a valid int, and therefore
between INT_MIN and INT_MAX.

This CAN'T work everywhere.

Yes, it can.
>>The u = -1 statement is legal, and results in UINT_MAX value. However
the first i = u statement always overruns the INT_MAX value for i,
unless the system has INT_MAX defined to be equal to UINT_MAX. Very
rare. So the result of that statement is implementation defined.

Of course. And any of the permissible implementation-defined values of
i will result in the intended behaviour.

I think you have a misinterpretation of 'implementaion-defined'. This
means that the action, on a particular implementation, is defined.
However that may well be "*** ABORT in line nnn, integer overflow ***".
If the result is implementation-defined, any result is permissible, but
there must be a result. If the behaviour is implementation-defined, any
behaviour (including, as you mention, exiting the program) is
permissible. In this case, the result is implementation-defined, and
exiting the program is not allowed.
Mar 14 '08 #77
user923005 <dc*****@connx.comwrites:
On Mar 14, 5:59*am, Martin <m...@b.cwrote:
<snip>
> printf("unsigned short max = %d\n", (short)((unsigned short) ~0 >1));

and so on.

Obviously, I don't know to what peer review T&G's Answer Book was subject, *
but if their solutions are not correct, I would like to know.

It works for two's complement.
Are you sure? What happens when both signed and unsigned short (or
indeed, int in the "and so on" case) have the same number of value
bits? I think this is permitted and causes the wrong answer to be
printed, but my brain is already hurting from thinking about this
exercise.
Maybe that's just the trick:
You have to write a different solution for each possible number
format.
I hoped I could find a portable solution that way, but I drew a blank.

--
Ben.
Mar 15 '08 #78
On Mar 14, 5:18*pm, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
user923005 <dcor...@connx.comwrites:
On Mar 14, 5:59*am, Martin <m...@b.cwrote:
<snip>
* *printf("unsigned short max = %d\n", (short)((unsigned short) ~0 >1));
and so on.
Obviously, I don't know to what peer review T&G's Answer Book was subject, *
but if their solutions are not correct, I would like to know.
It works for two's complement.

Are you sure? *What happens when both signed and unsigned short (or
indeed, int in the "and so on" case) have the same number of value
bits? *I think this is permitted and causes the wrong answer to be
printed, but my brain is already hurting from thinking about this
exercise.
*Maybe that's just the trick:
You have to write a different solution for each possible number
format.

I hoped I could find a portable solution that way, but I drew a blank.
You're right.
I think that every solution I have seen posted so far (including mine)
only works on a very limited subset of possible integer limit sets.
That makes this a very interesting exercise. And we have not even
touched the floating point yet.
Mar 15 '08 #79
On Mar 12, 5:37 am, santosh <santosh....@gmail.comwrote:
Hello all,

In K&R2 one exercise asks the reader to compute and print the limits for
the basic integer types. This is trivial for unsigned types. But is it
possible for signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants in limits.h cannot
be used.
Hi santosh

Maybe you could take this book for reference:
the c answer book 2Edtion by Clovis L. Tondo & Scott E. Gimpel

And,there is a way about signed char on that book
printf("signed char min = %d\n", -(char)((unsigned char) ~0 >1));

but i think it should be that
printf("signed char min = %d\n", -1 -(char)((unsigned char) ~0 >1));
maybe it's a little mistake of press :)

There aren't solutions about floats, i think the other book
Computer Systems A Programmer's Perspective by Randal E. Bryant &
David O'Hallaron
of CMU could help.

Good luck!
yalong
Mar 15 '08 #80
On Sat, 15 Mar 2008 02:39:40 -0000, yalong <ag*******@gmail.comwrote:
Maybe you could take this book for reference:
the c answer book 2Edtion by Clovis L. Tondo & Scott E. Gimpel

And,there is a way about signed char on that book
printf("signed char min = %d\n", -(char)((unsigned char) ~0 >1));

but i think it should be that
printf("signed char min = %d\n", -1 -(char)((unsigned char) ~0 >1));
maybe it's a little mistake of press :)
I think you've misread the symbol ~ as -. In another message in this
thread I posted this, an extract of T&G's solution:

printf("signed char min = %d\n", ~(char)((unsigned char) ~0 >1));
printf("signed char max = %d\n", (char)((unsigned char) ~0 >1));
printf("unsigned short min = %d\n", ~(short)((unsigned short) ~0 >1));
printf("unsigned short max = %d\n", (short)((unsigned short) ~0 >1));

--
Martin

Mar 16 '08 #81
On Mar 17, 6:19 am, Martin <martindotunderscoreobr...@which.tnet>
wrote:
On Sat, 15 Mar 2008 02:39:40 -0000, yalong <aginob...@gmail.comwrote:
Maybe you could take this book for reference:
the c answer book 2Edtion by Clovis L. Tondo & Scott E. Gimpel
And,there is a way about signed char on that book
printf("signed char min = %d\n", -(char)((unsigned char) ~0 >1));
but i think it should be that
printf("signed char min = %d\n", -1 -(char)((unsigned char) ~0 >1));
maybe it's a little mistake of press :)

I think you've misread the symbol ~ as -. In another message in this
thread I posted this, an extract of T&G's solution:

printf("signed char min = %d\n", ~(char)((unsigned char) ~0 >1));
printf("signed char max = %d\n", (char)((unsigned char) ~0 >1));
printf("unsigned short min = %d\n", ~(short)((unsigned short) ~0 >1));
printf("unsigned short max = %d\n", (short)((unsigned short) ~0 >1));

--
Martin
hi Martin,

Thanks about that. I got a misprint book of my language vision.
Both of them get the right value, maybe it's little different in
running time.

yalong
Mar 17 '08 #82
yalong <aginob...@gmail.comwrote:
santosh <santosh....@gmail.comwrote:Hello all,
In K&R2 one exercise asks the reader to compute and
print the limits for the basic integer types. This is
trivial for unsigned types. But is it possible for
signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants
in limits.h cannot be used.

Hi santosh

Maybe you could take this book for reference:
the c answer book 2Edtion by Clovis L. Tondo & Scott E. Gimpel
Or maybe you shouldn't.
And,there is a way about signed char on that book
printf("signed char min = %d\n",
-(char)((unsigned char) ~0 >1));
~0 may be a trap representation on sign-magnitude machines.
The (unsigned char) ~0 is much better stated as (unsigned
char) -1, which yields UCHAR_MAX portably. But the single
right shifting of that need not yield SCHAR_MAX.[*] The
further negation of that need not yield SCHAR_MIN.
[*] The standard doesn't preclude UCHAR_MAX == 65535 and
SCHAR_MAX == 127.
but i think it should be that
printf("signed char min = %d\n",
-1 -(char)((unsigned char) ~0 >1));
Excellent. All the flaws above and one more. ;)
maybe it's a little mistake of press :)
The cast conversion to _plain_ char is certainly a mistake,
even if inconsequencial in context. But I doubt it's a
printing error.

--
Peter
Mar 17 '08 #83
On Mar 16, 10:37*pm, Peter Nilsson <ai...@acay.com.auwrote:
yalong <aginob...@gmail.comwrote:
santosh <santosh....@gmail.comwrote:Hello all,
In K&R2 one exercise asks the reader to compute and
print the limits for the basic integer types. This is
trivial for unsigned types. But is it possible for
signed types without invoking undefined behaviour
triggered by overflow? Remember that the constants
in limits.h cannot be used.
Hi santosh
Maybe you could take this book for reference:
the c answer book 2Edtion by Clovis L. Tondo & Scott E. Gimpel

Or maybe you shouldn't.
And,there is a way about signed char on that book
printf("signed char min = %d\n",
*-(char)((unsigned char) ~0 >1));

~0 may be a trap representation on sign-magnitude machines.
The (unsigned char) ~0 is much better stated as (unsigned
char) -1, which yields UCHAR_MAX portably. But the single
right shifting of that need not yield SCHAR_MAX.[*] The
further negation of that need not yield SCHAR_MIN.
[*] The standard doesn't preclude UCHAR_MAX == 65535 and
SCHAR_MAX == 127.
but i think it should be that
printf("signed char min = %d\n",
* -1 -(char)((unsigned char) ~0 >1));

Excellent. All the flaws above and one more. ;)
maybe it's a little mistake of press :)

The cast conversion to _plain_ char is certainly a mistake,
even if inconsequencial in context. But I doubt it's a
printing error.

--
Peter
This seems rather simple to me, but perhaps it is just my
inexperience. Here is a solution that works on all of the platforms
I've worked with, but I haven't worked with ALL computers:
unsigned long long ULL_MAX = (unsigned long long)(-1LL);
unsigned long long ULL_MIN = 0ULL; //automatically known because the
smallest unsigned value is 0
signed long long SLL_MAX = (signed long long)(ULL_MAX >1);
signed long long SLL_MIN = SLL_MAX + 1;

It is also somewhat easily adaptable. Just change the types from long
long to another integral type!
Mar 17 '08 #84
rpgfan3233 said:

<snip>
This seems rather simple to me, but perhaps it is just my
inexperience. Here is a solution that works on all of the platforms
I've worked with, but I haven't worked with ALL computers:
unsigned long long ULL_MAX = (unsigned long long)(-1LL);
unsigned long long ULL_MIN = 0ULL; //automatically known because the
smallest unsigned value is 0
signed long long SLL_MAX = (signed long long)(ULL_MAX >1);
signed long long SLL_MIN = SLL_MAX + 1;
Presumably you mean SLL_MIN = -SLL_MAX - 1;

Unfortunately, this last one can break on sign-and-magnitude
implementations. Worse, as we were reminded quite recently, C doesn't
forbid implementations from setting U<int_type>_MAX equal to
<int_type>_MAX.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Mar 17 '08 #85
CBFalconer <cb********@yahoo.comwrites:
Ioannis Vranos wrote:
>>
... snip ...
>>
OK it is allowed, but is there any existing system where the value
ranges of signed int and unsigned int are different?

Yes. Consider a 16 bit system. INT_MAX is 32767. INT_MIN is
-32768 (or -32767). UINT_MAX is 65536 (UINT_MIN is naturally 0).
Or it would be 0 if it existed.
It is allowable to reserve the value that would represent -32768 to
indicate a special condition, such as uninitialized. Or, for a 1's
complement machine, the bit pattern for -0 is forbidden.
How does this answer the question? You've demonstrated that it's
allowed, which he already knows. The question is whether they're
different on any existing system. (The really interestion question,
IMHO, is "if so, which one?")

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Mar 17 '08 #86
Peter Nilsson <ai***@acay.com.auwrites:
yalong <aginob...@gmail.comwrote:
<snip>
>And,there is a way about signed char on that book
printf("signed char min = %d\n",
-(char)((unsigned char) ~0 >1));

~0 may be a trap representation on sign-magnitude machines.
Did you mean ones' complement? I thought sign bit = 1 and all value
bits 1 had to be well-defined on sign-magnitude systems.

On ones' complement systems, ~0 is either negative zero (and the
conversion to unsigned char will produce 0) or it is a trap
representation. The above code is definitely useless on such a
system.

--
Ben.
Mar 17 '08 #87
On Mar 18, 4:08*am, Ben Bacarisse <ben.use...@bsb.me.ukwrote:
Peter Nilsson <ai...@acay.com.auwrites:
yalong <aginob...@gmail.comwrote:
<snip>
And,there is a way about signed char on that book
printf("signed char min = %d\n",
*-(char)((unsigned char) ~0 >1));
~0 may be a trap representation on sign-magnitude machines.

Did you mean ones' complement?
Yes, thanks.

--
Peter
Mar 17 '08 #88
CBFalconer wrote:
Ioannis Vranos wrote:
... snip ...
>OK it is allowed, but is there any existing system where the value
ranges of signed int and unsigned int are different?

Yes. Consider a 16 bit system. INT_MAX is 32767. INT_MIN is
-32768 (or -32767). UINT_MAX is 65536 (UINT_MIN is naturally 0).
It is allowable to reserve the value that would represent -32768 to
indicate a special condition, such as uninitialized. Or, for a 1's
complement machine, the bit pattern for -0 is forbidden.
Off by one.. 65536 takes 17 bits. Happy St. Paddy's.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Mar 17 '08 #89

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.