Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #10378 > unrolled thread
| Started by | Stanley Rice <heconghui@gmail.com> |
|---|---|
| First post | 2011-09-16 22:07 -0700 |
| Last post | 2011-09-17 07:51 -0400 |
| Articles | 9 — 7 participants |
Back to article view | Back to comp.lang.c
maximum value of int Stanley Rice <heconghui@gmail.com> - 2011-09-16 22:07 -0700
Re: maximum value of int Ian Collins <ian-news@hotmail.com> - 2011-09-17 17:25 +1200
Re: maximum value of int Stanley Rice <heconghui@gmail.com> - 2011-09-17 00:47 -0700
Re: maximum value of int Paul N <gw7rib@aol.com> - 2011-09-17 03:53 -0700
Re: maximum value of int Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-17 12:17 +0100
Re: maximum value of int Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2011-09-17 10:31 -0600
Re: maximum value of int Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-09-17 19:51 +0100
Re: maximum value of int Keith Thompson <kst-u@mib.org> - 2011-09-17 14:39 -0700
Re: maximum value of int Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-09-17 07:51 -0400
| From | Stanley Rice <heconghui@gmail.com> |
|---|---|
| Date | 2011-09-16 22:07 -0700 |
| Subject | maximum value of int |
| Message-ID | <394fc242-c6ae-41ba-9861-6d4c88ec25b5@f17g2000yqh.googlegroups.com> |
Hello all
I don't know it is appropriate to post such a short or easy question
here. I couldn't understand some line of code abot maximum int value
as below:
#define INT_MAX (((unsigned)-1) >> 1)
The first time I saw it, I was confused why it could pass the
examination of the compiler. I try to make a bit modification, say
#define INT_TEST ((unsigned) - 1)
This time, the compiler also shuts its mouth, but when I try
#define INT_TEST (unsigned)
The compiler begins to shout to me.
I'm confused about why the type itself, i.e unsigned, could do
subtration. And it could generate an integer. But when I leave the
type alone, the compiler tries to stop me.
[toc] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2011-09-17 17:25 +1200 |
| Message-ID | <9dipadFr5dU3@mid.individual.net> |
| In reply to | #10378 |
On 09/17/11 05:07 PM, Stanley Rice wrote: > Hello all > > I don't know it is appropriate to post such a short or easy question > here. I couldn't understand some line of code abot maximum int value > as below: > > #define INT_MAX (((unsigned)-1)>> 1) > > The first time I saw it, I was confused why it could pass the > examination of the compiler. I try to make a bit modification, say > #define INT_TEST ((unsigned) - 1) > This time, the compiler also shuts its mouth, but when I try > #define INT_TEST (unsigned) > The compiler begins to shout to me. > > I'm confused about why the type itself, i.e unsigned, could do > subtration. And it could generate an integer. But when I leave the > type alone, the compiler tries to stop me. (unsigned)-1 is a cast, not a subtraction. -- Ian Collins
[toc] | [prev] | [next] | [standalone]
| From | Stanley Rice <heconghui@gmail.com> |
|---|---|
| Date | 2011-09-17 00:47 -0700 |
| Message-ID | <a8a298dc-0fd8-4f6f-834a-880d9b57d917@d12g2000vba.googlegroups.com> |
| In reply to | #10379 |
On Sep 17, 1:25 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> On 09/17/11 05:07 PM, Stanley Rice wrote:
>
>
>
>
>
>
>
>
>
> > Hello all
>
> > I don't know it is appropriate to post such a short or easy question
> > here. I couldn't understand some line of code abot maximum int value
> > as below:
>
> > #define INT_MAX (((unsigned)-1)>> 1)
>
> > The first time I saw it, I was confused why it could pass the
> > examination of the compiler. I try to make a bit modification, say
> > #define INT_TEST ((unsigned) - 1)
> > This time, the compiler also shuts its mouth, but when I try
> > #define INT_TEST (unsigned)
> > The compiler begins to shout to me.
>
> > I'm confused about why the type itself, i.e unsigned, could do
> > subtration. And it could generate an integer. But when I leave the
> > type alone, the compiler tries to stop me.
>
> (unsigned)-1 is a cast, not a subtraction.
>
> --
> Ian Collins
Oh yes, I got it! Thanks a lot. Now I want to know whether the
underlying representation (bit stream) of -1 in type int and type
unsigned are the same or not, suggesting type int is in 32 bit in my
machine. I guess the underlying representation of digit -1 is the
same, say,
1111 1111 1111 1111 1111 1111 1111 1111 (FFFFFFFF)
When we treat it as an signed int, it is decoded as a digit as int_val
= -1, and when we treat it as an unsigned int, it is decoded as a
digit as unsigned_val = 4294967295, could you tell me if my guess is
right or not?
If my assumption is right, then I am confused about the different
result of the following lines:
printf("%u\n", (unsigned)-1 >> 1); // 1
printf("%u\n", (unsigned)(-1 >> 1)); // 2
printf("%u\n", (unsigned)(-1 >> 2)); // 3
printf("%u\n", (unsigned)-1); // 4
The statement 1 prints 2147483647, which is what i want. But statement
2, 3, 4 all print the same, 4294967295. That is what I am confused
about. Why statement 1 and statement 2 generate different results? And
why statement 2, 3 and 4 generate the same result?
[toc] | [prev] | [next] | [standalone]
| From | Paul N <gw7rib@aol.com> |
|---|---|
| Date | 2011-09-17 03:53 -0700 |
| Message-ID | <6b1fdcbe-be90-42c0-bebf-b481b2e15067@c29g2000yqd.googlegroups.com> |
| In reply to | #10387 |
On Sep 17, 8:47 am, Stanley Rice <hecong...@gmail.com> wrote:
> On Sep 17, 1:25 pm, Ian Collins <ian-n...@hotmail.com> wrote:
>
>
>
>
>
> > On 09/17/11 05:07 PM, Stanley Rice wrote:
>
> > > Hello all
>
> > > I don't know it is appropriate to post such a short or easy question
> > > here.
That's fine!
> > > I couldn't understand some line of code abot maximum int value
> > > as below:
>
> > > #define INT_MAX (((unsigned)-1)>> 1)
If I remember correctly, it is up to the compiler to define INT_MAX.
When people are writing compilers, they are writing them for a
specific system and so they can use their knowledge of details of the
system. When *you* are writing programs, you can if you want to use
your knowledge of details of the system, but the point of C is to
allow a program to be run on any computer with a C compiler and so it
is often encouraged to make your programs "portable", ie not dependent
on the detailsof the particular system. So the code above (which I am
guessing you found in a header file of the compiler) is not
necessarily the sort of thing you'd write yourself.
(snip)
> Oh yes, I got it! Thanks a lot. Now I want to know whether the
> underlying representation (bit stream) of -1 in type int and type
> unsigned are the same or not, suggesting type int is in 32 bit in my
> machine. I guess the underlying representation of digit -1 is the
> same, say,
> 1111 1111 1111 1111 1111 1111 1111 1111 (FFFFFFFF)
> When we treat it as an signed int, it is decoded as a digit as int_val
> = -1, and when we treat it as an unsigned int, it is decoded as a
> digit as unsigned_val = 4294967295, could you tell me if my guess is
> right or not?
>
> If my assumption is right, then I am confused about the different
> result of the following lines:
> printf("%u\n", (unsigned)-1 >> 1); // 1
> printf("%u\n", (unsigned)(-1 >> 1)); // 2
> printf("%u\n", (unsigned)(-1 >> 2)); // 3
> printf("%u\n", (unsigned)-1); // 4
> The statement 1 prints 2147483647, which is what i want. But statement
> 2, 3, 4 all print the same, 4294967295. That is what I am confused
> about. Why statement 1 and statement 2 generate different results? And
> why statement 2, 3 and 4 generate the same result?
I think your problems here stem from the fact that in 2 and 3, the
number -1 is treated as an int, shifted and only then converted to an
unsigned. I'm guessing that when you shift a negative number you get
another negative number, so 1s are coming in at the front, leaving the
number unchanged as all 1s. It's a similar problem to:
(double) (1/3)
which gives a result of 0 as the division is done as integers and only
then converted to a double.
I'n not an expert on all this, though.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-09-17 12:17 +0100 |
| Message-ID | <0.f37d19adf02b5224e4cf.20110917121745BST.87y5xnv2na.fsf@bsb.me.uk> |
| In reply to | #10387 |
Stanley Rice <heconghui@gmail.com> writes:
<snip>
> Oh yes, I got it! Thanks a lot. Now I want to know whether the
> underlying representation (bit stream) of -1 in type int and type
> unsigned are the same or not, suggesting type int is in 32 bit in my
> machine. I guess the underlying representation of digit -1 is the
> same, say,
> 1111 1111 1111 1111 1111 1111 1111 1111 (FFFFFFFF)
> When we treat it as an signed int, it is decoded as a digit as int_val
> = -1, and when we treat it as an unsigned int, it is decoded as a
> digit as unsigned_val = 4294967295, could you tell me if my guess is
> right or not?
On must 32-bit machines, all ones represents either an unsigned int of
4294967295 or a signed int of -1.
> If my assumption is right, then I am confused about the different
> result of the following lines:
> printf("%u\n", (unsigned)-1 >> 1); // 1
> printf("%u\n", (unsigned)(-1 >> 1)); // 2
> printf("%u\n", (unsigned)(-1 >> 2)); // 3
> printf("%u\n", (unsigned)-1); // 4
> The statement 1 prints 2147483647, which is what i want. But statement
> 2, 3, 4 all print the same, 4294967295. That is what I am confused
> about. Why statement 1 and statement 2 generate different results? And
> why statement 2, 3 and 4 generate the same result?
C leaves the meaning of shifting a signed int with a negative value up
to the individual implementation. Your compiler chooses to use a"
sign-extending" shift. Thus -1 >> n where n < the bit width of the
integer will always be -1.
Do you have a book on C? Without a good one you might spend a lot of
time wondering about questions like this. A good book could answer many
of them at once.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Joe Pfeiffer <pfeiffer@cs.nmsu.edu> |
|---|---|
| Date | 2011-09-17 10:31 -0600 |
| Message-ID | <1blitnjfl8.fsf@pfeifferfamily.net> |
| In reply to | #10387 |
Stanley Rice <heconghui@gmail.com> writes:
>
> If my assumption is right, then I am confused about the different
> result of the following lines:
> printf("%u\n", (unsigned)-1 >> 1); // 1
> printf("%u\n", (unsigned)(-1 >> 1)); // 2
> printf("%u\n", (unsigned)(-1 >> 2)); // 3
> printf("%u\n", (unsigned)-1); // 4
> The statement 1 prints 2147483647, which is what i want. But statement
> 2, 3, 4 all print the same, 4294967295. That is what I am confused
> about. Why statement 1 and statement 2 generate different results? And
> why statement 2, 3 and 4 generate the same result?
My experience has always been that when experimenting with seeing it
patterns, I'm better off printing them in hexadecimal with a %08x (for a
32 bit system).
Anyway:
The first one is taking a -1, interpreting it as unsigned, and then
right-shifting one bit. Since it's unsigned, it shifts 0s in from the
left, so you get 7fffffff.
The other three are all doing the shift first (well, there is no shift
for the fourth one, but we'll see in a moment that that doesn't
matter). Because you're shifting a negative number, the shift is
shifting copies of the sign bit in. -1 is 0xffffffff; -1 right-shifted
by one (but shifting a 1 in on the left) is still 0xffffffff, and -1
right-shifted by two, but still copying the sign bit in, is still
0xffffffff.
IIRC, this behavior is not guaranteed by the standard.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2011-09-17 19:51 +0100 |
| Message-ID | <0.5c58c7e0d9bb4b2549ab.20110917195102BST.87obyjuhnt.fsf@bsb.me.uk> |
| In reply to | #10402 |
Joe Pfeiffer <pfeiffer@cs.nmsu.edu> writes:
> Stanley Rice <heconghui@gmail.com> writes:
>>
>> If my assumption is right, then I am confused about the different
>> result of the following lines:
>> printf("%u\n", (unsigned)-1 >> 1); // 1
>> printf("%u\n", (unsigned)(-1 >> 1)); // 2
>> printf("%u\n", (unsigned)(-1 >> 2)); // 3
>> printf("%u\n", (unsigned)-1); // 4
>> The statement 1 prints 2147483647, which is what i want. But statement
>> 2, 3, 4 all print the same, 4294967295. That is what I am confused
>> about. Why statement 1 and statement 2 generate different results? And
>> why statement 2, 3 and 4 generate the same result?
<snip>
> The first one is taking a -1, interpreting it as unsigned, and then
> right-shifting one bit. Since it's unsigned, it shifts 0s in from the
> left, so you get 7fffffff.
Minor quibble: the phrase "interpret as unsigned" might suggest that the
bits of -1 are treated as if they were unsigned, whereas the standard
calls this a conversion (from signed int to unsigned int) and it is
defined in terms of modular arithmetic such that the result *must* be
UINT_MAX (all value bits set to 1).
The difference is that on, for example, a sign+magnitude machine
(unsigned)-1 must still be UINT_MAX.
And just to round it off, what you said is perfectly correct on most
machines. The rules of signed to unsigned conversion are such that most
implementations can just interpret the bit pattern as if it were
unsigned and no actual code is needed to do the conversion.
> The other three are all doing the shift first (well, there is no shift
> for the fourth one, but we'll see in a moment that that doesn't
> matter). Because you're shifting a negative number, the shift is
> shifting copies of the sign bit in. -1 is 0xffffffff; -1 right-shifted
> by one (but shifting a 1 in on the left) is still 0xffffffff, and -1
> right-shifted by two, but still copying the sign bit in, is still
> 0xffffffff.
>
> IIRC, this behavior is not guaranteed by the standard.
The first part is guaranteed, but the second is implementation defined.
This one a machine can't easily do sign-extended shifts, a plain shift
can be used.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2011-09-17 14:39 -0700 |
| Message-ID | <lnpqiy7ss9.fsf@nuthaus.mib.org> |
| In reply to | #10387 |
Stanley Rice <heconghui@gmail.com> writes:
> On Sep 17, 1:25 pm, Ian Collins <ian-n...@hotmail.com> wrote:
>> On 09/17/11 05:07 PM, Stanley Rice wrote:
>> > I don't know it is appropriate to post such a short or easy question
>> > here. I couldn't understand some line of code abot maximum int value
>> > as below:
>>
>> > #define INT_MAX (((unsigned)-1)>> 1)
>>
>> > The first time I saw it, I was confused why it could pass the
>> > examination of the compiler. I try to make a bit modification, say
>> > #define INT_TEST ((unsigned) - 1)
>> > This time, the compiler also shuts its mouth, but when I try
>> > #define INT_TEST (unsigned)
>> > The compiler begins to shout to me.
>>
>> > I'm confused about why the type itself, i.e unsigned, could do
>> > subtration. And it could generate an integer. But when I leave the
>> > type alone, the compiler tries to stop me.
>>
>> (unsigned)-1 is a cast, not a subtraction.
>
> Oh yes, I got it! Thanks a lot. Now I want to know whether the
> underlying representation (bit stream) of -1 in type int and type
> unsigned are the same or not, suggesting type int is in 32 bit in my
> machine. I guess the underlying representation of digit -1 is the
> same, say,
> 1111 1111 1111 1111 1111 1111 1111 1111 (FFFFFFFF)
> When we treat it as an signed int, it is decoded as a digit as int_val
> = -1, and when we treat it as an unsigned int, it is decoded as a
> digit as unsigned_val = 4294967295, could you tell me if my guess is
> right or not?
The validity of the expression has (almost) nothing to do with how
signed and unsigned integeres are represented. That's not to say that
you shouldn't be curious about the representation, but it's not directly
relevant here.
1 is an expression of type int, with the obvious value.
-1 is an expression consisting of the unary "-" operator applied to 1.
It's also of type int, also with the obvious value.
(unsigned)-1 is a cast expression; the "(unsigned)" part is a cast
operator. It takes the value of the expression -1 and converts it
from type int to type unsigned int ("unsigned int" and "unsigned"
are simply two names for the same type). As I mentioned, that
conversion is not defined in terms of how either int or unsigned
int is represented; it's defined entirely in terms of *values*.
The result of this particular conversion is defined in the C
standard, section 6.3.1.3, paragraph 2:
Otherwise, if the new type is unsigned, the value is converted
by repeatedly adding or subtracting one more than the maximum
value that can be represented in the new type until the value
is in the range of the new type.
The "maximum value that can be represented in the new type" is
UINT_MAX. The result of the conversion is computed, in this case,
by adding UINT_MAX+1 to -1, which yields UINT_MAX. In general,
the value -1 converted to any unsigned type yields the maximum
value of that unsigned type.
Then we right-shift the result by 1 bit (>> 1), yielding UINT_MAX/2
(truncated). On most systems, that's going to be the value of
INT_MAX (though, as Eric Sosman points out, it's not of the right
type, nor is it suitable for use as the system's definition of
INT_MAX). It's possible for INT_MAX *not* to equal (((unsigned)-1)>>
1), but that can happen only in the presence of padding bits,
which are rare in modern systems.
(On a typical 32-bit system, UINT_MAX is 2**32-1, or 0xffffffff,
or 4294967295, and INT_MAX is 2**31-1, or 0x7fffffff, or 2147483647;
other values are possible. The "**" denotes expontiation; C doesn't
actually have a "**" operator.)
Now has it happens, the rule for converting signed int to unsigned int
works out very well for a typical 2's-complement system. The generated
code for the conversion doesn't really work by "repeatedly adding or
subtracting one more than the maximum value that can be represented in
the new type until the value is in the range of the new type". It does
the exact equivalent -- which happens to mean just copying or
reinterpreting the bits that make up the representation. An
implementation for a 1s'-complement or sign-and-magnitude system still
has to follow the same rule for conversion, even though it's less
convenient. The standard's definition of the conversion works entirely
in terms of values; the reason that definition is the way it is is that
it works well with the most common representation scheme. (And that's
why the standard's wording seems clumsy; it's describe something that
was originally about reinterpreting the representation, but doing so in
terms of mathematical values.)
> If my assumption is right, then I am confused about the different
> result of the following lines:
> printf("%u\n", (unsigned)-1 >> 1); // 1
> printf("%u\n", (unsigned)(-1 >> 1)); // 2
> printf("%u\n", (unsigned)(-1 >> 2)); // 3
> printf("%u\n", (unsigned)-1); // 4
> The statement 1 prints 2147483647, which is what i want. But statement
> 2, 3, 4 all print the same, 4294967295. That is what I am confused
> about. Why statement 1 and statement 2 generate different results? And
> why statement 2, 3 and 4 generate the same result?
If the left operand of a ">>" operator is negative, the result is
implementation-defined (C99 6.5.7p5). Shift operators are primarily
intended for use with unsigned, or at least non-negative, operands.
You could probably figure out why your lines 2 and 3 are producing
the results you're seeing, but I don't think the answer would be
very useful.
Your line 4 is printing the value of UINT_MAX, as explained above.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Eric Sosman <esosman@ieee-dot-org.invalid> |
|---|---|
| Date | 2011-09-17 07:51 -0400 |
| Message-ID | <j521km$4de$1@dont-email.me> |
| In reply to | #10378 |
On 9/17/2011 1:07 AM, Stanley Rice wrote:
> Hello all
>
> I don't know it is appropriate to post such a short or easy question
> here. I couldn't understand some line of code abot maximum int value
> as below:
>
> #define INT_MAX (((unsigned)-1)>> 1)
As an aside to the explanations others have provided, note that
this is not a valid way to define the INT_MAX macro in <limits.h>.
Although it will (very probably) have the correct numeric value, it
lacks two features required of the INT_MAX from <limits.h>:
- It is not an expression whose value the preprocessor can
compute, making it unusable in #if directives.
- Once evaluated, it is of the wrong type: `unsigned int'
instead of plain `int', a.k.a. `signed int'.
If your code does not include <limits.h>, directly or indirectly,
you are of course free to use the identifier INT_MAX however you like.
But it's a Very Bad Idea to use a Standard-described identifier in a
non-standard way, leading mostly to confusion and chaos. If you're
studying this person's code to improve your knowledge of C, be warned
that the author's own grasp of C may not be all that firm.
--
Eric Sosman
esosman@ieee-dot-org.invalid
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web