Velocity Reviews > Code problem

# Code problem

jacob navia
Guest
Posts: n/a

 12-06-2007
I posted this to comp.std.c, but may be of interest here too:

Consider this:

extern void abort(void);
int main (void)
{
unsigned long long xx;
unsigned long long *x = (unsigned long long *) &xx;

*x = -3;
*x = *x * *x;
if (*x != 9)
abort ();
return(0);
}

lcc-win interprets
*x = -3;
as
*x = 4294967293;
since x points to an UNSIGNED long long.
I cast the 32 bit integer -3 into an unsigned integer
then I cast the result to an unsigned long long.

Apparently gcc disagrees.

Am I doing something wrong somewhere?

I should first cast into a long long THEN into an unsigned
long long?

Thanks for your help.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32

Ben Pfaff
Guest
Posts: n/a

 12-06-2007
jacob navia <(E-Mail Removed)> writes:

> int main (void)
> {
> unsigned long long xx;
> unsigned long long *x = (unsigned long long *) &xx;

Why the cast? It should be unnecessary.

> *x = -3;
> *x = *x * *x;
> if (*x != 9)
> abort ();
> return(0);
> }
>
> lcc-win interprets
> *x = -3;
> as
> *x = 4294967293;
> since x points to an UNSIGNED long long.

unsigned long long has to be at least 64 bits in size.
18446744073709551613 is the minimum correct value for *x here.

> I cast the 32 bit integer -3 into an unsigned integer
> then I cast the result to an unsigned long long.

I don't see any cast to unsigned int in the above program.
--
Ben Pfaff
http://benpfaff.org

Richard Heathfield
Guest
Posts: n/a

 12-06-2007
jacob navia said:

> I posted this to comp.std.c, but may be of interest here too:
>
> Consider this:
>
> extern void abort(void);
> int main (void)
> {
> unsigned long long xx;
> unsigned long long *x = (unsigned long long *) &xx;

Remove the unnecessary cast:

unsigned long long *x = &xx;

>
> *x = -3;

See 6.2.5(9).

> *x = *x * *x;
> if (*x != 9)
> abort ();

It is deeply unlikely that *x will be 9 at this point.

> return(0);
> }
>
> lcc-win interprets
> *x = -3;
> as
> *x = 4294967293;
> since x points to an UNSIGNED long long.

That's a bug in lcc-win. *x must have the value ULLONG_MAX - 2, and since
ULLONG_MAX must be at least 18446744073709551615, *x must be at least
18446744073709551613.

> I cast the 32 bit integer -3 into an unsigned integer
> then I cast the result to an unsigned long long.

Why?

> Apparently gcc disagrees.
>
> Am I doing something wrong somewhere?

Yes. If your article is an accurate description of lcc-win's behaviour,
your mistake is in using a non-conforming compiler.

> I should first cast into a long long THEN into an unsigned
> long long?

No, there is almost certainly no need to cast anything at all. The first
step is to identify the problem you are trying to solve, which is far from
clear. If you want to know the result of multiplying -3 by -3, why use an
unsigned type in the first place?

--
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

jameskuyper@verizon.net
Guest
Posts: n/a

 12-06-2007
jacob navia wrote:
> I posted this to comp.std.c, but may be of interest here too:
>
> Consider this:
>
> extern void abort(void);
> int main (void)
> {
> unsigned long long xx;
> unsigned long long *x = (unsigned long long *) &xx;
>
> *x = -3;
> *x = *x * *x;
> if (*x != 9)
> abort ();
> return(0);
> }
>
> lcc-win interprets
> *x = -3;
> as
> *x = 4294967293;
> since x points to an UNSIGNED long long.

The minimum value for ULLONG_MAX is 18446744073709551615, so you
should be getting a value of at least 18446744073709551613

> I cast the 32 bit integer -3 into an unsigned integer
> then I cast the result to an unsigned long long.

Why did you do that?

> Apparently gcc disagrees.
>
> Am I doing something wrong somewhere?

Yes.

> I should first cast into a long long THEN into an unsigned
> long long?

Why do you think that? Why are you using intermediaries?

You should be converting -3 directly to unsigned long long. You should
neither detour through unsigned int, nor detour through long long. The
result should be ULLONG_MAX+1-3.

Ben Pfaff
Guest
Posts: n/a

 12-06-2007
Richard Heathfield <(E-Mail Removed)> writes:

> jacob navia said:
>> unsigned long long xx;
>> unsigned long long *x = (unsigned long long *) &xx;
>> *x = -3;
>> *x = *x * *x;
>> if (*x != 9)
>> abort ();

>
> It is deeply unlikely that *x will be 9 at this point.

2**64 - 3 == 18446744073709551613
(18446744073709551613)**2 = 340282366920938463352694142989510901769
340282366920938463352694142989510901769 % 2**64 = 9

At least according to the calculator I have here.
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}

Eric Sosman
Guest
Posts: n/a

 12-06-2007
jacob navia wrote:
> I posted this to comp.std.c, but may be of interest here too:
>
> Consider this:
>
> extern void abort(void);
> int main (void)
> {
> unsigned long long xx;
> unsigned long long *x = (unsigned long long *) &xx;

What is the cast for? (Hint: What is the type of
the expression `&xx'?)

> *x = -3;
> *x = *x * *x;
> if (*x != 9)
> abort ();
> return(0);
> }
>
> lcc-win interprets
> *x = -3;
> as
> *x = 4294967293;

That cannot possibly be correct. ULLONG_MAX is at
least 18446744073709551615, so ULLONG_MAX-2 (the required
result) is at least 18446744073709551614.

> since x points to an UNSIGNED long long.
> I cast the 32 bit integer -3 into an unsigned integer
> then I cast the result to an unsigned long long.

That would be correct iff ULLONG_MAX==ULONG_MAX.

Imagine converting a signed char to an unsigned long
by the analogous route. Let's assume an 8-bit char, a
16-bit int, and a 32-bit long (and because there's no
way to write a literal of type char, I'll need to use
a variable instead):

signed char sc = -3;
unsigned long ul = sc;

The procedure you've outlined would convert sc to an
unsigned int, getting 65533u, and then convert that value
to unsigned long, yielding 65533ul. Yet the correct
result is ULONG_MAX-2 == 4294967293. The intermediate
conversion has lost sign information that affects the
ultimate result.

> Apparently gcc disagrees.
>
> Am I doing something wrong somewhere?
>
> I should first cast into a long long THEN into an unsigned
> long long?

You should convert the signed int to unsigned long long
by adding or subtracting ULLONG_MAX+1 the appropriate number
of times: in this case, by adding it once.

--
http://www.velocityreviews.com/forums/(E-Mail Removed)

jacob navia
Guest
Posts: n/a

 12-06-2007
Ben Pfaff wrote:
> jacob navia <(E-Mail Removed)> writes:
>
>> int main (void)
>> {
>> unsigned long long xx;
>> unsigned long long *x = (unsigned long long *) &xx;

>
> Why the cast? It should be unnecessary.
>
>> *x = -3;
>> *x = *x * *x;
>> if (*x != 9)
>> abort ();
>> return(0);
>> }
>>
>> lcc-win interprets
>> *x = -3;
>> as
>> *x = 4294967293;
>> since x points to an UNSIGNED long long.

>
> unsigned long long has to be at least 64 bits in size.
> 18446744073709551613 is the minimum correct value for *x here.
>
>> I cast the 32 bit integer -3 into an unsigned integer
>> then I cast the result to an unsigned long long.

>
> I don't see any cast to unsigned int in the above program.

Of course not. The casts were the result of loading a 32 bit constant
and extending it to a 64 bit constant in assembly.

I was missing the sign extend in the process.

Conceptually however, what is
(unsigned)-3

???

supposing sizeof(int)=4
sizeof(long long)=8

-3 is 4294967293

When you write "-3" that is a signed integer constant, in my system
32 bits, i.e. the above number.

When I do a sign extend, then it works
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32

jacob navia
Guest
Posts: n/a

 12-06-2007
Ben Pfaff wrote:
> Richard Heathfield <(E-Mail Removed)> writes:
>
>> jacob navia said:
>>> unsigned long long xx;
>>> unsigned long long *x = (unsigned long long *) &xx;
>>> *x = -3;
>>> *x = *x * *x;
>>> if (*x != 9)
>>> abort ();

>> It is deeply unlikely that *x will be 9 at this point.

>
> 2**64 - 3 == 18446744073709551613
> (18446744073709551613)**2 = 340282366920938463352694142989510901769
> 340282366920938463352694142989510901769 % 2**64 = 9
>
> At least according to the calculator I have here.

Yes, it should be 9. I was missing a sign extend when
converting a signed int into an unsigned long long.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32

jacob navia
Guest
Posts: n/a

 12-06-2007
(E-Mail Removed) wrote:
> jacob navia wrote:
>> I posted this to comp.std.c, but may be of interest here too:
>>
>> Consider this:
>>
>> extern void abort(void);
>> int main (void)
>> {
>> unsigned long long xx;
>> unsigned long long *x = (unsigned long long *) &xx;
>>
>> *x = -3;
>> *x = *x * *x;
>> if (*x != 9)
>> abort ();
>> return(0);
>> }
>>
>> lcc-win interprets
>> *x = -3;
>> as
>> *x = 4294967293;
>> since x points to an UNSIGNED long long.

>
> The minimum value for ULLONG_MAX is 18446744073709551615, so you
> should be getting a value of at least 18446744073709551613
>
>> I cast the 32 bit integer -3 into an unsigned integer
>> then I cast the result to an unsigned long long.

>
> Why did you do that?
>
>> Apparently gcc disagrees.
>>
>> Am I doing something wrong somewhere?

>
> Yes.
>
>> I should first cast into a long long THEN into an unsigned
>> long long?

>
> Why do you think that? Why are you using intermediaries?
>
> You should be converting -3 directly to unsigned long long. You should
> neither detour through unsigned int, nor detour through long long. The
> result should be ULLONG_MAX+1-3.

Yes, I was missing a sign extend.

But the abstract problem is still not clear to me. I mean when I see
a number like

-3

unadorned this is a signed integer constant. Since I am assigning it to
an unsigned value, I reinterpret the bits as an unsigned (this is my
mistake probably) and then convert THAT into an unsigned long long.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32

jameskuyper@verizon.net
Guest
Posts: n/a

 12-06-2007
jacob navia wrote:
....
> Conceptually however, what is
> (unsigned)-3

It is a quantity which is utterly and completely irrelevant to this
code. It's value is UINT_MAX+1-3.

> supposing sizeof(int)=4
> sizeof(long long)=8
>
> -3 is 4294967293

I can't figure out any sense in which that statement is true. What is
true is that

(unsigned long long)-3 == ULLONG_MAX+1-3

and sizeof(int) has no relevance to that answer whatsoever.

 Thread Tools

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post thedarkman HTML 5 09-13-2010 11:40 PM keithb ASP .Net 1 03-29-2006 01:00 AM Alan Silver ASP .Net 1 09-15-2005 05:23 PM mwkohout@gmail.com Java 0 02-14-2005 06:06 PM =?Utf-8?B?Q2FybG8gTWFyY2hlc29uaQ==?= ASP .Net 4 02-11-2004 07:31 AM

Advertisments