strange output on openbsd C code

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|

strange output on openbsd C code

Gustavo Rios
I am writing a very simple program but the output change for the c
variable value change every time i run it. What would it be my mistake
on the source? Did i forget some thing?

#include <stdio.h>

int
main(int argc, char **argv)
{
        unsigned long long      x, c;
        unsigned                *p;

        x = 1, x+= (unsigned long long)1 << 33 ;
        p = (void *)&x;
        c = p[0] * p[1];

        fprintf(stdout, "x:%llu\n", x);
        fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
        fprintf(stdout, "c:%llu\n", c);

        return 0;
}

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Nick Guenther
On 3/19/07, Gustavo Rios <[hidden email]> wrote:

> I am writing a very simple program but the output change for the c
> variable value change every time i run it. What would it be my mistake
> on the source? Did i forget some thing?
>
> #include <stdio.h>
>
> int
> main(int argc, char **argv)
> {
>         unsigned long long      x, c;
>         unsigned                *p;

^ this is bad. always say your types in full.

>
>         x = 1, x+= (unsigned long long)1 << 33 ;

This sets *(&x) to 1, and then sets *(&x) (yes, the same one) to 1+(1<<33)

>         p = (void *)&x;
>         c = p[0] * p[1];

That is, p[1] == *(&x+1) is never getting set to anything. Thus the
reason the output is always changing is because p[1] is always
pointing at a different, random location in memory that has some
previous value.

Further, p[1] is not your memory, and it's only by chance that you're
not segfaulting.

>         fprintf(stdout, "x:%llu\n", x);
>         fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
>         fprintf(stdout, "c:%llu\n", c);
>
>         return 0;
> }
>


-Nick

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Gustavo Rios
So, why when i printf p[1], it correctly prints 2?

On 3/19/07, Nick ! <[hidden email]> wrote:

> On 3/19/07, Gustavo Rios <[hidden email]> wrote:
> > I am writing a very simple program but the output change for the c
> > variable value change every time i run it. What would it be my mistake
> > on the source? Did i forget some thing?
> >
> > #include <stdio.h>
> >
> > int
> > main(int argc, char **argv)
> > {
> >         unsigned long long      x, c;
> >         unsigned                *p;
>
> ^ this is bad. always say your types in full.
>
> >
> >         x = 1, x+= (unsigned long long)1 << 33 ;
>
> This sets *(&x) to 1, and then sets *(&x) (yes, the same one) to 1+(1<<33)
>
> >         p = (void *)&x;
> >         c = p[0] * p[1];
>
> That is, p[1] == *(&x+1) is never getting set to anything. Thus the
> reason the output is always changing is because p[1] is always
> pointing at a different, random location in memory that has some
> previous value.
>
> Further, p[1] is not your memory, and it's only by chance that you're
> not segfaulting.
>
> >         fprintf(stdout, "x:%llu\n", x);
> >         fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
> >         fprintf(stdout, "c:%llu\n", c);
> >
> >         return 0;
> > }
> >
>
>
> -Nick

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Nick Guenther
On 3/19/07, Gustavo Rios <[hidden email]> wrote:

>
> On 3/19/07, Nick ! <[hidden email]> wrote:
> > On 3/19/07, Gustavo Rios <[hidden email]> wrote:
> > > I am writing a very simple program but the output change for the c
> > > variable value change every time i run it. What would it be my mistake
> > > on the source? Did i forget some thing?
> > >
> > > #include <stdio.h>
> > >
> > > int
> > > main(int argc, char **argv)
> > > {
> > >         unsigned long long      x, c;
> > >         unsigned                *p;
> >
> > ^ this is bad. always say your types in full.
> >
> > >
> > >         x = 1, x+= (unsigned long long)1 << 33 ;
> >
> > This sets *(&x) to 1, and then sets *(&x) (yes, the same one) to 1+(1<<33)
> >
> > >         p = (void *)&x;
> > >         c = p[0] * p[1];
> >
> > That is, p[1] == *(&x+1) is never getting set to anything. Thus the
> > reason the output is always changing is because p[1] is always
> > pointing at a different, random location in memory that has some
> > previous value.
> >
> > Further, p[1] is not your memory, and it's only by chance that you're
> > not segfaulting.
> >
> > >         fprintf(stdout, "x:%llu\n", x);
> > >         fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
> > >         fprintf(stdout, "c:%llu\n", c);
> > >
> > >         return 0;
> > > }
> > >
> So, why when i printf p[1], it correctly prints 2?

Uhm. Hmm. Well, x is a long long which is 8 bytes right? A void (when
doing pointer arithmetic) is taken to only be 1 byte (right?). So p[0]
is the first byte of those 8, and p[1] is the second, and due to
coincidence and twos-complement encoding it happens to show you the
expected numbers. Maybe?

But that doesn't explain why the output is always changing.

Wait, how is * defined on two voids????? That shouldn't even compile
(unless it's autocasting to int?).

-Nick

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Frank Denis (Jedi/Sector One)-4
In reply to this post by Gustavo Rios
Le Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios ecrivait :
>I am writing a very simple program but the output change for the c
>variable value change every time i run it.
>int
>main(int argc, char **argv)
>{
>        unsigned long long      x, c;
>        unsigned                *p;
>        p = (void *)&x;
>        fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);

  p is the address of x. That address is not supposed to be anything fixed.    

--
Frank Denis - j [at] pureftpd.org - My geeky blog: http://00f.net

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Gustavo Rios
In reply to this post by Nick Guenther
No!

p sizeof is 4 bytes, p is the frst byt of &x, and p + 1 is the 4th
byte. Casting is only on attribution of &x to p.

Realize, p[0] evals to 1 and p[1] evals to 2 as it should be. Only
problem relates to p[0] * p[1]. I believe it should (1 * 2), i.e., 2.
Not a random value.

On 3/19/07, Nick ! <[hidden email]> wrote:

> On 3/19/07, Gustavo Rios <[hidden email]> wrote:
> >
> > On 3/19/07, Nick ! <[hidden email]> wrote:
> > > On 3/19/07, Gustavo Rios <[hidden email]> wrote:
> > > > I am writing a very simple program but the output change for the c
> > > > variable value change every time i run it. What would it be my mistake
> > > > on the source? Did i forget some thing?
> > > >
> > > > #include <stdio.h>
> > > >
> > > > int
> > > > main(int argc, char **argv)
> > > > {
> > > >         unsigned long long      x, c;
> > > >         unsigned                *p;
> > >
> > > ^ this is bad. always say your types in full.
> > >
> > > >
> > > >         x = 1, x+= (unsigned long long)1 << 33 ;
> > >
> > > This sets *(&x) to 1, and then sets *(&x) (yes, the same one) to 1+(1<<33)
> > >
> > > >         p = (void *)&x;
> > > >         c = p[0] * p[1];
> > >
> > > That is, p[1] == *(&x+1) is never getting set to anything. Thus the
> > > reason the output is always changing is because p[1] is always
> > > pointing at a different, random location in memory that has some
> > > previous value.
> > >
> > > Further, p[1] is not your memory, and it's only by chance that you're
> > > not segfaulting.
> > >
> > > >         fprintf(stdout, "x:%llu\n", x);
> > > >         fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
> > > >         fprintf(stdout, "c:%llu\n", c);
> > > >
> > > >         return 0;
> > > > }
> > > >
> > So, why when i printf p[1], it correctly prints 2?
>
> Uhm. Hmm. Well, x is a long long which is 8 bytes right? A void (when
> doing pointer arithmetic) is taken to only be 1 byte (right?). So p[0]
> is the first byte of those 8, and p[1] is the second, and due to
> coincidence and twos-complement encoding it happens to show you the
> expected numbers. Maybe?
>
> But that doesn't explain why the output is always changing.
>
> Wait, how is * defined on two voids????? That shouldn't even compile
> (unless it's autocasting to int?).
>
> -Nick

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

David Higgs
Whenever a printf "fixes everything", it's usually because that forces
gcc to put the values on the stack.  Without the printf, they're
probably in registers and p points to who knows what.

If you grok assembly, try objdump on the executable to see what's
going on.  If you want to multiply the two halves of a long long, I'd
suggest shifting and masking it out explicitly instead of using
pointer tricks like this.

--david

On 3/19/07, Gustavo Rios <[hidden email]> wrote:

> No!
>
> p sizeof is 4 bytes, p is the frst byt of &x, and p + 1 is the 4th
> byte. Casting is only on attribution of &x to p.
>
> Realize, p[0] evals to 1 and p[1] evals to 2 as it should be. Only
> problem relates to p[0] * p[1]. I believe it should (1 * 2), i.e., 2.
> Not a random value.
>
> On 3/19/07, Nick ! <[hidden email]> wrote:
> > On 3/19/07, Gustavo Rios <[hidden email]> wrote:
> > >
> > > On 3/19/07, Nick ! <[hidden email]> wrote:
> > > > On 3/19/07, Gustavo Rios <[hidden email]> wrote:
> > > > > I am writing a very simple program but the output change for the c
> > > > > variable value change every time i run it. What would it be my mistake
> > > > > on the source? Did i forget some thing?
> > > > >
> > > > > #include <stdio.h>
> > > > >
> > > > > int
> > > > > main(int argc, char **argv)
> > > > > {
> > > > >         unsigned long long      x, c;
> > > > >         unsigned                *p;
> > > >
> > > > ^ this is bad. always say your types in full.
> > > >
> > > > >
> > > > >         x = 1, x+= (unsigned long long)1 << 33 ;
> > > >
> > > > This sets *(&x) to 1, and then sets *(&x) (yes, the same one) to 1+(1<<33)
> > > >
> > > > >         p = (void *)&x;
> > > > >         c = p[0] * p[1];
> > > >
> > > > That is, p[1] == *(&x+1) is never getting set to anything. Thus the
> > > > reason the output is always changing is because p[1] is always
> > > > pointing at a different, random location in memory that has some
> > > > previous value.
> > > >
> > > > Further, p[1] is not your memory, and it's only by chance that you're
> > > > not segfaulting.
> > > >
> > > > >         fprintf(stdout, "x:%llu\n", x);
> > > > >         fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
> > > > >         fprintf(stdout, "c:%llu\n", c);
> > > > >
> > > > >         return 0;
> > > > > }
> > > > >
> > > So, why when i printf p[1], it correctly prints 2?
> >
> > Uhm. Hmm. Well, x is a long long which is 8 bytes right? A void (when
> > doing pointer arithmetic) is taken to only be 1 byte (right?). So p[0]
> > is the first byte of those 8, and p[1] is the second, and due to
> > coincidence and twos-complement encoding it happens to show you the
> > expected numbers. Maybe?
> >
> > But that doesn't explain why the output is always changing.
> >
> > Wait, how is * defined on two voids????? That shouldn't even compile
> > (unless it's autocasting to int?).
> >
> > -Nick

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Paul D. Ouderkirk
In reply to this post by Gustavo Rios
On 3/19/07, Gustavo Rios <[hidden email]> wrote:
> No!
>
> p sizeof is 4 bytes, p is the frst byt of &x, and p + 1 is the 4th
> byte. Casting is only on attribution of &x to p.
>
> Realize, p[0] evals to 1 and p[1] evals to 2 as it should be. Only
> problem relates to p[0] * p[1]. I believe it should (1 * 2), i.e., 2.
> Not a random value.

For what it's worth, when I run this code I always get the same
(presumably correct) values:

pdo@paroxysm:~ $ ./a.out
x:8589934593
0,1:1,2
c:2

pdo@paroxysm:~ $ uname -rm
4.0 i386

--
------------------------------
Paul D. Ouderkirk
Senior UNIX System Administrator
JadedPixel Technologies
[hidden email]
------------------------------
laughing,
in the mechanism
-- William Gibson

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Paul D. Ouderkirk
On 3/19/07, Paul D. Ouderkirk <[hidden email]> wrote:

> On 3/19/07, Gustavo Rios <[hidden email]> wrote:
> > No!
> >
> > p sizeof is 4 bytes, p is the frst byt of &x, and p + 1 is the 4th
> > byte. Casting is only on attribution of &x to p.
> >
> > Realize, p[0] evals to 1 and p[1] evals to 2 as it should be. Only
> > problem relates to p[0] * p[1]. I believe it should (1 * 2), i.e., 2.
> > Not a random value.
>
> For what it's worth, when I run this code I always get the same
> (presumably correct) values:
>

And because I love to reply to myself, if I compile it with -O3, I can
reproduce your results:

pdo@paroxysm:~ $ cc -O3 test.c
pdo@paroxysm:~ $ ./a.out
x:8589934593
0,1:1,2
c:1387628864   (value of c changes with every execution)

--
------------------------------
Paul D. Ouderkirk
Senior UNIX System Administrator
JadedPixel Technologies
[hidden email]
------------------------------
laughing,
in the mechanism
-- William Gibson

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Matthew R. Dempsky
In reply to this post by Frank Denis (Jedi/Sector One)-4
On Tue, Mar 20, 2007 at 01:35:28AM +0100, Frank Denis wrote:

> Le Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios ecrivait :
> >I am writing a very simple program but the output change for the c
> >variable value change every time i run it.
> >int
> >main(int argc, char **argv)
> >{
> >       unsigned long long      x, c;
> >       unsigned                *p;
> >       p = (void *)&x;
> >       fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
>
>  p is the address of x. That address is not supposed to be anything fixed.  

He never prints p.

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Matthew R. Dempsky
In reply to this post by Nick Guenther
On Mon, Mar 19, 2007 at 08:02:10PM -0400, Nick ! wrote:
> Wait, how is * defined on two voids????? That shouldn't even compile
> (unless it's autocasting to int?).

``unsigned'' is short for ``unsigned int''.  The ``(void *)'' cast is
a red herring.

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Darrin Chandler
In reply to this post by Gustavo Rios
On Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios wrote:

> I am writing a very simple program but the output change for the c
> variable value change every time i run it. What would it be my mistake
> on the source? Did i forget some thing?
>
> #include <stdio.h>
>
> int
> main(int argc, char **argv)
> {
>        unsigned long long      x, c;
>        unsigned                *p;
>
>        x = 1, x+= (unsigned long long)1 << 33 ;
>        p = (void *)&x;
>        c = p[0] * p[1];
>
>        fprintf(stdout, "x:%llu\n", x);
>        fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
>        fprintf(stdout, "c:%llu\n", c);
>
>        return 0;
> }

I run this many times, with other stuff in between, and I always get:

$ ./gustavo
x:8589934593
0,1:1,2
c:2

Same values for everything, every time. Hmm.

--
Darrin Chandler                   |  Phoenix BSD Users Group
[hidden email]          |  http://bsd.phoenix.az.us/
http://www.stilyagin.com/darrin/  |

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

a.velichinsky
On Mon, Mar 19, 2007 at 07:17:46PM -0700, Darrin Chandler wrote:

> On Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios wrote:
> > I am writing a very simple program but the output change for the c
> > variable value change every time i run it. What would it be my mistake
> > on the source? Did i forget some thing?
> >
> > #include <stdio.h>
> >
> > int
> > main(int argc, char **argv)
> > {
> >        unsigned long long      x, c;
> >        unsigned                *p;
> >
> >        x = 1, x+= (unsigned long long)1 << 33 ;
> >        p = (void *)&x;
> >        c = p[0] * p[1];
> >
> >        fprintf(stdout, "x:%llu\n", x);
> >        fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
> >        fprintf(stdout, "c:%llu\n", c);
> >
> >        return 0;
> > }
>
> I run this many times, with other stuff in between, and I always get:
>
> $ ./gustavo
> x:8589934593
> 0,1:1,2
> c:2
>
> Same values for everything, every time. Hmm.

Compile it with -O3. Then enjoy.

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Adam-29
In reply to this post by Gustavo Rios
"Gustavo Rios" <[hidden email]> wrote:

> I am writing a very simple program but the output change for the c
> variable value change every time i run it. What would it be my mistake
> on the source? Did i forget some thing?

Bleh, what a depressing thread.  Gustavo, why didn't you bother to
provide all the relevant info, like that you are foolishly compiling
with -O3?  Its pretty well known that gcc doesn't always produce correct
output when using optimizations more aggressive than -O2.  Stop using
-O3 and suddenly it prints 2 all the time.  Looks like this bug is
fixed in gcc 4.2 at least.

And what is with the "answers" being provided guys?  Its only 8 lines,
and its not that hard to follow.  Guessing random "answers" isn't
usually very helpful, maybe reading it and saying "there's nothing
wrong with that code, are you using compiler optimizations?" would
work better.  At least a few people tried it instead of making up
non-existant bugs in the code.

Adam

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Darrin Chandler
In reply to this post by Darrin Chandler
On Tue, Mar 20, 2007 at 04:40:08AM +0200, [hidden email] wrote:
> Compile it with -O3. Then enjoy.

Sure. Then I'll light my hair on fire and put it out with a ballpeen
hammer.

--
Darrin Chandler                   |  Phoenix BSD Users Group
[hidden email]          |  http://bsd.phoenix.az.us/
http://www.stilyagin.com/darrin/  |

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Matthew R. Dempsky
In reply to this post by Paul D. Ouderkirk
On Mon, Mar 19, 2007 at 09:55:04PM -0400, Paul D. Ouderkirk wrote:
> And because I love to reply to myself, if I compile it with -O3, I can
> reproduce your results:

-O3 enables -fstrict-aliasing, which this program violates.  The man
page explains in more detail.

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Tobias Ulmer
In reply to this post by Gustavo Rios
On Mon, Mar 19, 2007 at 07:12:24PM -0300, Gustavo Rios wrote:

> I am writing a very simple program but the output change for the c
> variable value change every time i run it. What would it be my mistake
> on the source? Did i forget some thing?
>
> #include <stdio.h>
>
> int
> main(int argc, char **argv)
> {
>        unsigned long long      x, c;
>        unsigned                *p;
>
/* stop abusing the comma operator */
>        x = 1, x+= (unsigned long long)1 << 33 ;
/* Fine, storing random void * pointers in p is allowd */
>        p = (void *)&x;
/*
 * You assume that the in memory representation of an
 * unsigned [2] looks exactly like unsigned long long and you
 * expect to access the valid initialized memory of x by
 * dereferencing p.
 *
 * These assumptions are all wrong.
 */

>        c = p[0] * p[1];
>
>        fprintf(stdout, "x:%llu\n", x);
>        fprintf(stdout, "0,1:%u,%u\n", p[0], p[1]);
>        fprintf(stdout, "c:%llu\n", c);
>
>        return 0;
> }
>
>

Your program is invalid. Gcc has all rights to fuck it up,
-omg-optimized or not.

Casts are basically syntactic sugar for "(i know what i'm doing, now
shut up and stop complaining)". Remove the (void *) and compile with
-Wall.

Tobias

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Woodchuck-2
On Tue, 20 Mar 2007, Tobias Ulmer wrote:

 ....

> /*
>  * You assume that the in memory representation of an
>  * unsigned [2] looks exactly like unsigned long long and you
>  * expect to access the valid initialized memory of x by
>  * dereferencing p.
>  *
>  * These assumptions are all wrong.
>  */

 ....

Indeed.

The error is very similar to making assumptions about how
the internal structure of x, p and c might relate in the
commonly seen:

        union roach_motel {
                unsigned long long x;
                unsigned int p[2];
                unsigned char c[8];
        } foo;  /* draws bugs */

We haven't even scratched the surface of the subtle joys of
big-endian addressing schemes (note the plural) or alignment
requirements in some architectures.

> Your program is invalid. Gcc has all rights to fuck it up,
> -omg-optimized or not.

It's not strictly invalid, it just doesn't follow the programmer's
intent.  This is the most difficult sort of bug to find for the
original programmer ("code blindness"), but a stranger can find it
more easily.  Now if we take code like the example program, and
intersperse a few thousand lines of other code, and break it all
up over a hundred functions (and files, and bury the declarations
about 5 deep in include files), put half the bug in a library, we
have the makings of a Windoze-grade nightmare. Add some conditionals,
we can write it so that the problem with uninitialized "c" only
shows up one run in a thousand.  0xDEADBEEF comes to mind...

> Casts are basically syntactic sugar for "(i know what i'm doing, now
> shut up and stop complaining)". Remove the (void *) and compile with
> -Wall.

Some casts are "READ MY MIND, DAMN IT!".  In this case, we notice
that cc -O2 and cc -O3 have different psychic skills.

I murmur again about "alignment issues", which don't exist for
the i386 architecture, as far as I know, except as an optimization.
(And certain obscure features of the PeeCee like DMA.)

The C standard is full of references to alignment.
In some architectures, I believe  
        void *p,*q;  p=(long *)1;  q=(char *)1;  
        p==q will be false.

To the OP:  you can't do both bit-wise manipulation and arithmetic
and expect the results to be always what you think.  Besides "endian"
issues and "alignment" issues, there can be questions of arithmetic
(2s-complement, 1s-complement, and others).  The PeeCee has blinded
many to the rich diversity of hardware possibilities.

Sometimes you just have to drag out the assembler.
       
Dave
--
     Resistance is futile.  You've already been assembled.

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Otto Moerbeek
In reply to this post by Matthew R. Dempsky
On Mon, 19 Mar 2007, Matthew R. Dempsky wrote:

> On Mon, Mar 19, 2007 at 09:55:04PM -0400, Paul D. Ouderkirk wrote:
> > And because I love to reply to myself, if I compile it with -O3, I can
> > reproduce your results:
>
> -O3 enables -fstrict-aliasing, which this program violates.  The man
> page explains in more detail.

Yep, it's a bit sad to see all the attempts at explaining the bug. But
this one hits the mark.

Additionally, while stock gcc enables -fstrict-aliasing with -O2, on
OpenBSD -fstrict-aliasing is not enabled with -O2, since experience
shows violations of pointer aliasing rules are seen a lot in the wild.

See man gcc-local:

-   The -O2 option does not include -fstrict-aliasing, as this option
    causes issues on some legacy code.  -fstrict-aliasing is very unsafe
    with code that plays tricks with casts, bypassing the already weak
    type system of C.

So don't play tricks like that unless you really understand the issues
involved.

        -Otto

Reply | Threaded
Open this post in threaded view
|

Re: strange output on openbsd C code

Stuart Henderson
In reply to this post by Gustavo Rios
On 2007/03/19 19:12, Gustavo Rios wrote:
> I am writing a very simple program but the output change for the c
> variable value change every time i run it.

It doesn't do this on any system I've tried it on -

>i386, amd64:

x:8589934593
0,1:1,2
c:2

>sparc64:

x:8589934593
0,1:2,1
c:2