comparing sizes of two structures

Discussion in 'C Programming' started by subramanian100in@yahoo.com, India, Mar 7, 2007.

  1. , India

    , India Guest

    Suppose there are five DISTINCT types TYPE1, TYPE2, TYPE3, TYPE4,
    TYPE5, of data.

    Consider the structures:

    struct struct_one
    {
    TYPE1 data1;
    TYPE2 data2;
    TYPE3 data3;
    TYPE4 data4;
    TYPE5 data5;
    } var_one;

    struct struct_two
    {
    TYPE2 data1;
    TYPE5 data2;
    TYPE1 data3;
    TYPE3 data4;
    TYPE4 data5;
    } var_two;

    How do the sizes of var_one and var_two compare - will they be the
    same or different ?
     
    , India, Mar 7, 2007
    #1
    1. Advertising

  2. , India

    Ian Collins Guest

    , India wrote:
    > Suppose there are five DISTINCT types TYPE1, TYPE2, TYPE3, TYPE4,
    > TYPE5, of data.
    >
    > Consider the structures:
    >
    > struct struct_one
    > {
    > TYPE1 data1;
    > TYPE2 data2;
    > TYPE3 data3;
    > TYPE4 data4;
    > TYPE5 data5;
    > } var_one;
    >
    > struct struct_two
    > {
    > TYPE2 data1;
    > TYPE5 data2;
    > TYPE1 data3;
    > TYPE3 data4;
    > TYPE4 data5;
    > } var_two;
    >
    > How do the sizes of var_one and var_two compare - will they be the
    > same or different ?
    >

    Either, it depends on the types and the implementation.

    --
    Ian Collins.
     
    Ian Collins, Mar 7, 2007
    #2
    1. Advertising

  3. , India

    santosh Guest

    , India wrote:
    > Suppose there are five DISTINCT types TYPE1, TYPE2, TYPE3, TYPE4,
    > TYPE5, of data.
    >
    > Consider the structures:
    >
    > struct struct_one
    > {
    > TYPE1 data1;
    > TYPE2 data2;
    > TYPE3 data3;
    > TYPE4 data4;
    > TYPE5 data5;
    > } var_one;
    >
    > struct struct_two
    > {
    > TYPE2 data1;
    > TYPE5 data2;
    > TYPE1 data3;
    > TYPE3 data4;
    > TYPE4 data5;
    > } var_two;
    >
    > How do the sizes of var_one and var_two compare - will they be the
    > same or different ?


    It depends on the compiler and the characteristics, (mainly alignment
    requirements), of your types.
     
    santosh, Mar 7, 2007
    #3
  4. , India

    jaysome Guest

    On 7 Mar 2007 00:16:50 -0800, ", India"
    <> wrote:

    >Suppose there are five DISTINCT types TYPE1, TYPE2, TYPE3, TYPE4,
    >TYPE5, of data.
    >
    >Consider the structures:
    >
    >struct struct_one
    > {
    > TYPE1 data1;
    > TYPE2 data2;
    > TYPE3 data3;
    > TYPE4 data4;
    > TYPE5 data5;
    >} var_one;
    >
    >struct struct_two
    > {
    > TYPE2 data1;
    > TYPE5 data2;
    > TYPE1 data3;
    > TYPE3 data4;
    > TYPE4 data5;
    >} var_two;
    >
    >How do the sizes of var_one and var_two compare - will they be the
    >same or different ?


    They could be the same or they could be different. It depends on the
    exact types of TYPE* and on the compiler. Compilers can add padding in
    order to align fields on their natural boundaries, and there is no
    guarantee that one compiler will pack fields the same as another
    compiler, especially so when the compilers target different platforms.

    Try compiling and running the following:

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

    typedef char TYPE1;
    typedef double TYPE2;
    typedef int TYPE3;
    typedef short TYPE4;
    typedef long TYPE5;

    struct s1
    {
    TYPE1 d1;
    TYPE2 d2;
    TYPE3 d3;
    TYPE4 d4;
    TYPE5 d5;
    } var_one;

    struct s2
    {
    TYPE2 d1;
    TYPE5 d2;
    TYPE1 d3;
    TYPE3 d4;
    TYPE4 d5;
    } var_two;

    int main(void)
    {
    printf("s1 offsets:\n");
    printf("offsetof(d1) = %d\n", (int)offsetof(struct s1, d1));
    printf("offsetof(d2) = %d\n", (int)offsetof(struct s1, d2));
    printf("offsetof(d3) = %d\n", (int)offsetof(struct s1, d3));
    printf("offsetof(d4) = %d\n", (int)offsetof(struct s1, d4));
    printf("offsetof(d5) = %d\n", (int)offsetof(struct s1, d5));

    printf("\n");
    printf("s2 offsets:\n");
    printf("offsetof(d1) = %d\n", (int)offsetof(struct s2, d1));
    printf("offsetof(d2) = %d\n", (int)offsetof(struct s2, d2));
    printf("offsetof(d3) = %d\n", (int)offsetof(struct s2, d3));
    printf("offsetof(d4) = %d\n", (int)offsetof(struct s2, d4));
    printf("offsetof(d5) = %d\n", (int)offsetof(struct s2, d5));

    return 0;
    }

    My conforming C implementation outputs:

    s1 offsets:
    offsetof(d1) = 0
    offsetof(d2) = 8
    offsetof(d3) = 16
    offsetof(d4) = 20
    offsetof(d5) = 24

    s2 offsets:
    offsetof(d1) = 0
    offsetof(d2) = 8
    offsetof(d3) = 12
    offsetof(d4) = 16
    offsetof(d5) = 20
    Press any key to continue

    Regards
    --
    jay
     
    jaysome, Mar 7, 2007
    #4
  5. , India <> wrote:
    >How do the sizes of var_one and var_two compare - will they be the
    >same or different ?


    Like others have said, it depends, but I'd answer in general "probably
    different".

    In the last big project I worked on, we'd allocate tons of structures at
    run time, and the platform was relatively limited in memory. As part of
    our optimizations, we went back and rearranged the fields in the structs
    by hand so the compiler would put less padding in.

    We realized significant memory savings.

    -Beej
     
    Beej Jorgensen, Mar 7, 2007
    #5
  6. , India

    Chris Dollin Guest

    , India wrote:

    > Suppose there are five DISTINCT types TYPE1, TYPE2, TYPE3, TYPE4,
    > TYPE5, of data.
    >
    > Consider the structures:
    >
    > struct struct_one
    > {
    > TYPE1 data1;
    > TYPE2 data2;
    > TYPE3 data3;
    > TYPE4 data4;
    > TYPE5 data5;
    > } var_one;
    >
    > struct struct_two
    > {
    > TYPE2 data1;
    > TYPE5 data2;
    > TYPE1 data3;
    > TYPE3 data4;
    > TYPE4 data5;
    > } var_two;
    >
    > How do the sizes of var_one and var_two compare - will they be the
    > same or different ?


    Yes, one or the other.

    Why do you care?

    --
    Chris "electric hedgehog" Dollin
    "Possibly you're not recalling some of his previous plans." Zoe, /Firefly/
     
    Chris Dollin, Mar 7, 2007
    #6
  7. , India

    santosh Guest

    jaysome wrote:
    > On 7 Mar 2007 00:16:50 -0800, ", India"
    > <> wrote:
    >
    > >Suppose there are five DISTINCT types TYPE1, TYPE2, TYPE3, TYPE4,
    > >TYPE5, of data.
    > >
    > >Consider the structures:
    > >
    > >struct struct_one
    > > {
    > > TYPE1 data1;
    > > TYPE2 data2;
    > > TYPE3 data3;
    > > TYPE4 data4;
    > > TYPE5 data5;
    > >} var_one;
    > >
    > >struct struct_two
    > > {
    > > TYPE2 data1;
    > > TYPE5 data2;
    > > TYPE1 data3;
    > > TYPE3 data4;
    > > TYPE4 data5;
    > >} var_two;
    > >
    > >How do the sizes of var_one and var_two compare - will they be the
    > >same or different ?


    [ ... ]

    > Try compiling and running the following:
    >
    > #include <stddef.h>
    > #include <stdio.h>
    >
    > typedef char TYPE1;
    > typedef double TYPE2;
    > typedef int TYPE3;
    > typedef short TYPE4;
    > typedef long TYPE5;
    >
    > struct s1
    > {
    > TYPE1 d1;
    > TYPE2 d2;
    > TYPE3 d3;
    > TYPE4 d4;
    > TYPE5 d5;
    > } var_one;
    >
    > struct s2
    > {
    > TYPE2 d1;
    > TYPE5 d2;
    > TYPE1 d3;
    > TYPE3 d4;
    > TYPE4 d5;
    > } var_two;
    >
    > int main(void)
    > {
    > printf("s1 offsets:\n");
    > printf("offsetof(d1) = %d\n", (int)offsetof(struct s1, d1));
    > printf("offsetof(d2) = %d\n", (int)offsetof(struct s1, d2));
    > printf("offsetof(d3) = %d\n", (int)offsetof(struct s1, d3));
    > printf("offsetof(d4) = %d\n", (int)offsetof(struct s1, d4));
    > printf("offsetof(d5) = %d\n", (int)offsetof(struct s1, d5));
    >
    > printf("\n");
    > printf("s2 offsets:\n");
    > printf("offsetof(d1) = %d\n", (int)offsetof(struct s2, d1));
    > printf("offsetof(d2) = %d\n", (int)offsetof(struct s2, d2));
    > printf("offsetof(d3) = %d\n", (int)offsetof(struct s2, d3));
    > printf("offsetof(d4) = %d\n", (int)offsetof(struct s2, d4));
    > printf("offsetof(d5) = %d\n", (int)offsetof(struct s2, d5));
    >
    > return 0;
    > }


    Why do cast the type size_t value yielded by offsetof into int?

    <snip>
     
    santosh, Mar 7, 2007
    #7
  8. , India

    Chris Dollin Guest

    santosh wrote:

    > jaysome wrote:


    (quelle snippage!)

    >> printf("offsetof(d5) = %d\n", (int)offsetof(struct s2, d5));
    >>
    >> return 0;
    >> }

    >
    > Why do cast the type size_t value yielded by offsetof into int?


    So they can print them using %d?

    --
    Chris "electric hedgehog" Dollin
    The shortcuts are all full of people using them.
     
    Chris Dollin, Mar 7, 2007
    #8
  9. , India

    santosh Guest

    Chris Dollin wrote:
    > santosh wrote:
    >
    > > jaysome wrote:

    >
    > (quelle snippage!)
    >
    > >> printf("offsetof(d5) = %d\n", (int)offsetof(struct s2, d5));
    > >>
    > >> return 0;
    > >> }

    > >
    > > Why do cast the type size_t value yielded by offsetof into int?

    >
    > So they can print them using %d?


    I know that. I would've myself used %lu, if %zu was not possible,
    (since jaysome appears to use Microsoft's Visual C++, which doesn't
    implement C99).

    So it was a bit strange.
     
    santosh, Mar 7, 2007
    #9
  10. santosh wrote:
    > Chris Dollin wrote:
    >> santosh wrote:
    >>
    >>> jaysome wrote:

    >> (quelle snippage!)
    >>
    >>>> printf("offsetof(d5) = %d\n", (int)offsetof(struct s2, d5));
    >>>>
    >>>> return 0;
    >>>> }
    >>> Why do cast the type size_t value yielded by offsetof into int?

    >> So they can print them using %d?

    >
    > I know that. I would've myself used %lu, if %zu was not possible,


    So you'd cast to long instead of int.

    > (since jaysome appears to use Microsoft's Visual C++, which doesn't
    > implement C99).


    Microsoft is one of funny vendors who have long smaller than size_t.

    Yevgen
     
    Yevgen Muntyan, Mar 7, 2007
    #10
  11. , India

    Rahul Guest

    hi,
    you can handle this byte alignment issue by using
    __attribute__((__packed__)) with each structure element. then each one
    of them will be allocated only minimum number of bytes needed.You can
    save the memory requirements if u have huge structures.
    thanx.
    rk.
    , India wrote:
    > Suppose there are five DISTINCT types TYPE1, TYPE2, TYPE3, TYPE4,
    > TYPE5, of data.
    >
    > Consider the structures:
    >
    > struct struct_one
    > {
    > TYPE1 data1;
    > TYPE2 data2;
    > TYPE3 data3;
    > TYPE4 data4;
    > TYPE5 data5;
    > } var_one;
    >
    > struct struct_two
    > {
    > TYPE2 data1;
    > TYPE5 data2;
    > TYPE1 data3;
    > TYPE3 data4;
    > TYPE4 data5;
    > } var_two;
    >
    > How do the sizes of var_one and var_two compare - will they be the
    > same or different ?
     
    Rahul, Mar 7, 2007
    #11
  12. On 7 Mar 2007 06:54:09 -0800, "Rahul" <>
    wrote:
    >you can handle this byte alignment issue by using
    >__attribute__((__packed__)) with each structure element. then each one
    >of them will be allocated only minimum number of bytes needed.You can
    >save the memory requirements if u have huge structures.


    This is an implementation specific feature and is not portable.

    When you are offering implementation specific suggestions, it would be
    a very good idea to mark it as such.

    Have a nice day,
    Pradeep
    --
    All opinions are mine and do not represent the views or
    policies of my employer.
    R Pradeep Chandran rpc AT pobox DOT com
     
    R Pradeep Chandran, Mar 7, 2007
    #12
  13. , India

    Dan Becker Guest

    <> wrote in message
    news:...
    > Suppose there are five DISTINCT types TYPE1, TYPE2, TYPE3, TYPE4,
    > TYPE5, of data.
    >
    > Consider the structures:
    >
    > struct struct_one
    > {
    > TYPE1 data1;
    > TYPE2 data2;
    > TYPE3 data3;
    > TYPE4 data4;
    > TYPE5 data5;
    > } var_one;
    >
    > struct struct_two
    > {
    > TYPE2 data1;
    > TYPE5 data2;
    > TYPE1 data3;
    > TYPE3 data4;
    > TYPE4 data5;
    > } var_two;
    >
    > How do the sizes of var_one and var_two compare - will they be the
    > same or different ?
    >

    might be different, or might be same.
    The sizes could be different, depending on what TYPE[1-5] are, and what
    aliignment constraints are imposed by the platform.

    Dan
     
    Dan Becker, Mar 7, 2007
    #13
  14. , India

    Flash Gordon Guest

    Yevgen Muntyan wrote, On 07/03/07 14:15:
    > santosh wrote:
    >> Chris Dollin wrote:
    >>> santosh wrote:
    >>>
    >>>> jaysome wrote:
    >>> (quelle snippage!)
    >>>
    >>>>> printf("offsetof(d5) = %d\n", (int)offsetof(struct s2, d5));
    >>>>>
    >>>>> return 0;
    >>>>> }
    >>>> Why do cast the type size_t value yielded by offsetof into int?
    >>> So they can print them using %d?

    >>
    >> I know that. I would've myself used %lu, if %zu was not possible,

    >
    > So you'd cast to long instead of int.


    No, read it again. Santosh would have to cast to unsigned long. Casting
    size_t to an unsigned type makes far more sense than a signed type
    (size_t being unsigned). unsigned long makes sense because it is the
    largest unsigned type a C90 implementation is guaranteed to have.

    >> (since jaysome appears to use Microsoft's Visual C++, which doesn't
    >> implement C99).

    >
    > Microsoft is one of funny vendors who have long smaller than size_t.


    It does make a certain amount of sense on 64 bit platforms. Although I
    would have gone for increasing the size of long to 64 bits myself.
    --
    Flash Gordon
     
    Flash Gordon, Mar 7, 2007
    #14
  15. , India

    matevzb Guest

    On Mar 7, 3:15 pm, Yevgen Muntyan <> wrote:
    <snip>
    > > (since jaysome appears to use Microsoft's Visual C++, which doesn't
    > > implement C99).

    >
    > Microsoft is one of funny vendors who have long smaller than size_t.

    Um... not on my 32-bit (XP), they're both 4 bytes and size_t is a
    typedef to unsigned int. On 64-bit it's a typedef to __int64, and
    (IIRC) they decided to stick with 32-bit long.
    --
    WYCIWYG - what you C is what you get
     
    matevzb, Mar 7, 2007
    #15
  16. Flash Gordon wrote:
    > Yevgen Muntyan wrote, On 07/03/07 14:15:
    >> santosh wrote:
    >>> Chris Dollin wrote:
    >>>> santosh wrote:
    >>>>
    >>>>> jaysome wrote:
    >>>> (quelle snippage!)
    >>>>
    >>>>>> printf("offsetof(d5) = %d\n", (int)offsetof(struct s2, d5));
    >>>>>>
    >>>>>> return 0;
    >>>>>> }
    >>>>> Why do cast the type size_t value yielded by offsetof into int?
    >>>> So they can print them using %d?
    >>>
    >>> I know that. I would've myself used %lu, if %zu was not possible,

    >>
    >> So you'd cast to long instead of int.

    >
    > No, read it again. Santosh would have to cast to unsigned long. Casting
    > size_t to an unsigned type makes far more sense than a signed type
    > (size_t being unsigned). unsigned long makes sense because it is the
    > largest unsigned type a C90 implementation is guaranteed to have.


    Wording sloppiness, "long" meant "unsigned long", I just wanted
    to say he'd cast anyway (and for practical purposes int is as good
    if you take structure offset).

    >>> (since jaysome appears to use Microsoft's Visual C++, which doesn't
    >>> implement C99).

    >>
    >> Microsoft is one of funny vendors who have long smaller than size_t.

    >
    > It does make a certain amount of sense on 64 bit platforms. Although I
    > would have gone for increasing the size of long to 64 bits myself.


    Yes, it's win64. I also agree it's no good.

    Yevgen
     
    Yevgen Muntyan, Mar 7, 2007
    #16
  17. matevzb wrote:
    > On Mar 7, 3:15 pm, Yevgen Muntyan <> wrote:
    > <snip>
    >>> (since jaysome appears to use Microsoft's Visual C++, which doesn't
    >>> implement C99).

    >> Microsoft is one of funny vendors who have long smaller than size_t.

    > Um... not on my 32-bit (XP), they're both 4 bytes and size_t is a
    > typedef to unsigned int. On 64-bit it's a typedef to __int64, and
    > (IIRC) they decided to stick with 32-bit long.


    So long is 4 bytes, and size_t is 8 bytes, i.e. long is smaller than
    size_t (where "smaller" means sizeof...).

    Yevgen
     
    Yevgen Muntyan, Mar 7, 2007
    #17
  18. , India

    Flash Gordon Guest

    Yevgen Muntyan wrote, On 07/03/07 17:51:
    > Flash Gordon wrote:
    >> Yevgen Muntyan wrote, On 07/03/07 14:15:
    >>> santosh wrote:
    >>>> Chris Dollin wrote:
    >>>>> santosh wrote:
    >>>>>
    >>>>>> jaysome wrote:
    >>>>> (quelle snippage!)
    >>>>>
    >>>>>>> printf("offsetof(d5) = %d\n", (int)offsetof(struct s2, d5));
    >>>>>>>
    >>>>>>> return 0;
    >>>>>>> }
    >>>>>> Why do cast the type size_t value yielded by offsetof into int?
    >>>>> So they can print them using %d?
    >>>>
    >>>> I know that. I would've myself used %lu, if %zu was not possible,
    >>>
    >>> So you'd cast to long instead of int.

    >>
    >> No, read it again. Santosh would have to cast to unsigned long.
    >> Casting size_t to an unsigned type makes far more sense than a signed
    >> type (size_t being unsigned). unsigned long makes sense because it is
    >> the largest unsigned type a C90 implementation is guaranteed to have.

    >
    > Wording sloppiness, "long" meant "unsigned long", I just wanted
    > to say he'd cast anyway (and for practical purposes int is as good
    > if you take structure offset).


    It makes a big difference to the correctness of the code.

    >>>> (since jaysome appears to use Microsoft's Visual C++, which doesn't
    >>>> implement C99).
    >>>
    >>> Microsoft is one of funny vendors who have long smaller than size_t.

    >>
    >> It does make a certain amount of sense on 64 bit platforms. Although I
    >> would have gone for increasing the size of long to 64 bits myself.

    >
    > Yes, it's win64. I also agree it's no good.


    Read what I said again. It does make a certain amount of sense, it is
    just not what I would have done. MS wanted to avoid breaking other
    peoples code more than they needed to (possibly their own as well) and
    made the choice on that basis.
    --
    Flash Gordon
     
    Flash Gordon, Mar 7, 2007
    #18
  19. "Rahul" <> writes:
    > you can handle this byte alignment issue by using
    > __attribute__((__packed__)) with each structure element. then each one
    > of them will be allocated only minimum number of bytes needed.You can
    > save the memory requirements if u have huge structures.

    [...]

    Please don't top-post. See:
    http://www.caliburn.nl/topposting.html
    http://www.cpax.org.uk/prg/writings/topposting.php

    Please don't use silly abbreviations like "u". This isn't a chat
    room. Nobody expects perfect English, but please do take the effort
    to spell out words.

    "__attribute__((__packed__))" is a compiler-specific extension.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Mar 7, 2007
    #19
  20. , India

    Guest

    On Mar 7, 12:38 pm, Flash Gordon <> wrote:
    > Yevgen Muntyan wrote, On 07/03/07 17:51:
    >
    >
    >
    > > Flash Gordon wrote:
    > >> Yevgen Muntyan wrote, On 07/03/07 14:15:
    > >>> santosh wrote:
    > >>>> Chris Dollin wrote:
    > >>>>> santosh wrote:

    >
    > >>>>>> jaysome wrote:
    > >>>>> (quelle snippage!)

    >
    > >>>>>>> printf("offsetof(d5) = %d\n", (int)offsetof(struct s2, d5));

    >
    > >>>>>>> return 0;
    > >>>>>>> }
    > >>>>>> Why do cast the type size_t value yielded by offsetof into int?
    > >>>>> So they can print them using %d?

    >
    > >>>> I know that. I would've myself used %lu, if %zu was not possible,

    >
    > >>> So you'd cast to long instead of int.

    >
    > >> No, read it again. Santosh would have to cast to unsigned long.
    > >> Casting size_t to an unsigned type makes far more sense than a signed
    > >> type (size_t being unsigned). unsigned long makes sense because it is
    > >> the largest unsigned type a C90 implementation is guaranteed to have.

    >
    > > Wording sloppiness, "long" meant "unsigned long", I just wanted
    > > to say he'd cast anyway (and for practical purposes int is as good
    > > if you take structure offset).

    >
    > It makes a big difference to the correctness of the code.


    It's easier to write %d and (int) in ten line programs whose whole
    purpose is to print structure member offsets. Note that the
    program *was* correct (there doesn't exist a computer where
    2*sizeof(double)+2*sizeof(long)+padding > INTMAX).
    Besides, ironically, cast to unsigned long is almost as bad
    as cast to int. If implementation was sufficiently weird (which
    it isn't), both could break. unsigned long is as correct
    as int: both can break (in weird theory); both ranges are smaller than
    size_t range on some *existing* implementations; both work on all
    existing implementations. Once something goes out the int range,
    it will break on win64 if you use long ;)

    > >>>> (since jaysome appears to use Microsoft's Visual C++, which doesn't
    > >>>> implement C99).

    >
    > >>> Microsoft is one of funny vendors who have long smaller than size_t.

    >
    > >> It does make a certain amount of sense on 64 bit platforms. Although I
    > >> would have gone for increasing the size of long to 64 bits myself.

    >
    > > Yes, it's win64. I also agree it's no good.

    >
    > Read what I said again. It does make a certain amount of sense, it is
    > just not what I would have done. MS wanted to avoid breaking other
    > peoples code more than they needed to (possibly their own as well) and
    > made the choice on that basis.


    Sorry, I read "not what I would have done" as "it would be better in
    my opinion not to make that". It is not quite "no good", so I could
    not agree it's no good since you didn't say it's no good. I apologize
    for making it look like I think you think MS did no good thing.

    Yevgen
     
    , Mar 7, 2007
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. tweak
    Replies:
    14
    Views:
    2,788
    Eric Sosman
    Jun 11, 2004
  2. Alfonso Morra
    Replies:
    11
    Views:
    721
    Emmanuel Delahaye
    Sep 24, 2005
  3. comparing two structures

    , Sep 14, 2007, in forum: C Programming
    Replies:
    18
    Views:
    816
    Richard Heathfield
    Sep 16, 2007
  4. Joel VanderWerf
    Replies:
    2
    Views:
    95
  5. Alec Taylor
    Replies:
    0
    Views:
    166
    Alec Taylor
    Mar 2, 2012
Loading...

Share This Page