468,257 Members | 1,410 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

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

Casting a byte array to allow assignment

I found the following code floating around somewhere and I'd like to
get some comments.

unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;

// now a1[0]=a2[0], a1[1]=a2[1], etc.

This is taking a byte array, casting it to a 4 byte integer pointer,
then dereferencing it, then assigning it. This results in the contents
of array a1 copied to array a2. (corrections to my interpretation
welcome)

I don't know why this was done this way. My first instinct would have
been to use memcpy. Is this faster than memcpy? Are there any dangers
other than the potential for int not being 4 bytes?

Jul 24 '06 #1
20 3074
quantumred wrote:
>
I found the following code floating around somewhere and I'd like to
get some comments.

unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;

// now a1[0]=a2[0], a1[1]=a2[1], etc.

This is taking a byte array, casting it to a 4 byte integer pointer,
then dereferencing it, then assigning it. This results in the contents
of array a1 copied to array a2. (corrections to my interpretation
welcome)

I don't know why this was done this way. My first instinct would have
been to use memcpy. Is this faster than memcpy? Are there any dangers
other than the potential for int not being 4 bytes?
There's the possibility that a1 and a2 don't
have the proper alignment for type unsigned.

--
pete
Jul 24 '06 #2

probably a little quicker then memcpy, no function call overhead.

prob. safe if you know how your compiler treats these types, or you can
set appropriate command line params to your compiler (or use some
pragmas)
to force alignment and so on.

Not really worth the trouble i suspect though: not at all clear what is
happening, and
what you gonna save? a few instructions on a P4/Athlon/etc is nothin!

Jul 24 '06 #3
Aaron Gage wrote:

Please quote what you are replying to, Google now makes this easy. See
the last link in my sig for more information.

The code in question was:
quantumred wrote:

I found the following code floating around somewhere and I'd like to
get some comments.

unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;

// now a1[0]=a2[0], a1[1]=a2[1], etc.

This is taking a byte array, casting it to a 4 byte integer pointer,
then dereferencing it, then assigning it. This results in the contents
of array a1 copied to array a2. (corrections to my interpretation
welcome)

I don't know why this was done this way. My first instinct would have
been to use memcpy. Is this faster than memcpy? Are there any dangers
other than the potential for int not being 4 bytes?
probably a little quicker then memcpy, no function call overhead.
On most modern compiler there is probably no difference in speed.
prob. safe if you know how your compiler treats these types, or you can
set appropriate command line params to your compiler (or use some
pragmas)
to force alignment and so on.
Definitely *not* safe. It might work on the OPs specific platform, but
it is not safe because the code might then get reused on a system where
it does not work.
Not really worth the trouble i suspect though: not at all clear what is
happening, and
what you gonna save? a few instructions on a P4/Athlon/etc is nothin!
Definitely not worth the trouble.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jul 24 '06 #4
quantumred posted:
unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;

This will work perfectly if:

(1) 4 == sizeof(int)

(2) alignof(char[4]) >= alignof(int)
The C Standard does not provide these guarantees for all platforms and
implementations. What you have is non-portable, platform-specific code.

It seems to me that the author was aiming to optimise the copying of an
array. I'd probably take a route somewhat akin to the following:

#define DEFINE_SOLE_MEMBER(Type) \
\
struct SoleMember##Type { \
Type obj; \
} /* Usage code provides semi-colon */ \

#define SoleMember(Type) SoleMember##Type

int main()
{
unsigned char a1[4]= {5,10,15,20};
unsigned char a2[4]= {25,30,35,40};

typedef char char4[4];

DEFINE_SOLE_MEMBER(char4);

*(SoleMember(char4)*)a1 = *(SoleMember(char4) const*)a2;
}
(The Standard guarantees that you can cast from a pointer to a struct, to a
pointer to the type of its first member. However, I don't believe it
guarantees the reverse -- so the code might be slightly dubious.)

--

Frederick Gotham
Jul 24 '06 #5
Frederick Gotham wrote:
quantumred posted:

>>unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;

This will work perfectly if:

(1) 4 == sizeof(int)

(2) alignof(char[4]) >= alignof(int)
The C Standard does not provide these guarantees for all platforms and
implementations. What you have is non-portable, platform-specific code.

It seems to me that the author was aiming to optimise the copying of an
array. I'd probably take a route somewhat akin to the following:

#define DEFINE_SOLE_MEMBER(Type) \
\
struct SoleMember##Type { \
Type obj; \
} /* Usage code provides semi-colon */ \

#define SoleMember(Type) SoleMember##Type

int main()
{
unsigned char a1[4]= {5,10,15,20};
unsigned char a2[4]= {25,30,35,40};

typedef char char4[4];

DEFINE_SOLE_MEMBER(char4);

*(SoleMember(char4)*)a1 = *(SoleMember(char4) const*)a2;
}
(The Standard guarantees that you can cast from a pointer to a struct, to a
pointer to the type of its first member. However, I don't believe it
guarantees the reverse -- so the code might be slightly dubious.)
In particular, it doesn't solve the alignment issue. The
alignment requirement for a struct object need not be a simple
function of the alignment requirements of its elements; the fact
that the enclosing object is a struct may impose alignment
requirements of its own. Therefore, either or both of the casts
in the above code may produce invalid struct pointers.

It also doesn't solve the size issue. The sizeof a struct
is at least as great as the sum of the sizeof its elements, but
may be greater. In the code above, sizeof(SoleMemberchar4) may
be greater than sizeof(char4), and if so the assignment tries to
read from memory beyond the end of the a2[] array, and undefined
behavior ensues.

One is left to ask: What issue *does* the above code solve?
Is it in any way better than the broken original, or is it just
a more sophisticated expression of the same errors?

--
Eric Sosman
es*****@acm-dot-org.invalid
Jul 24 '06 #6
Eric Sosman posted:
One is left to ask: What issue *does* the above code solve?
Is it in any way better than the broken original, or is it just
a more sophisticated expression of the same errors?

The code makes the (naive?) assumption that a struct consisting of a sole
member is identical to the member on its own.

Is this guaranteed? No.

Is it reasonable? I don't know, but it sounds sort of logical.
<OFF-TOPIC>
You've just given me an idea for a post to comp.std.c++.
</OFF-TOPIC>

--

Frederick Gotham
Jul 24 '06 #7
Frederick Gotham <fg*******@SPAM.comwrites:
quantumred posted:
>unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;

This will work perfectly if:

(1) 4 == sizeof(int)

(2) alignof(char[4]) >= alignof(int)
(3) unsigned int does not have trap representations, etc.
--
"The way I see it, an intelligent person who disagrees with me is
probably the most important person I'll interact with on any given
day."
--Billy Chambless
Jul 24 '06 #8
Frederick Gotham <fg*******@SPAM.comwrites:
quantumred posted:
>unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;


This will work perfectly if:

(1) 4 == sizeof(int)

(2) alignof(char[4]) >= alignof(int)
The C Standard does not provide these guarantees for all platforms and
implementations.
[...]

Nor does it provide a function or operator called "alignof".

(That's not a complaint, just a clarification; your hypothetical
"alignof" operator is a good way to express the idea.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Jul 24 '06 #9
"quantumred" <qu********@gmail.comwrote:
# I found the following code floating around somewhere and I'd like to
# get some comments.
#
# unsigned char a1[4]= { 5,10,15,20};
# unsigned char a2[4]= { 25,30,35,40};
#
# *(unsigned int *)a1=*(unsigned int *)a2;
#
# // now a1[0]=a2[0], a1[1]=a2[1], etc.
#
# This is taking a byte array, casting it to a 4 byte integer pointer,
# then dereferencing it, then assigning it. This results in the contents
# of array a1 copied to array a2. (corrections to my interpretation
# welcome)
#
# I don't know why this was done this way. My first instinct would have
# been to use memcpy. Is this faster than memcpy? Are there any dangers
# other than the potential for int not being 4 bytes?

If you have a 32 bit data path between memory and cpu, it's 4 times
faster to move an aligned word at a time instead of a byte at a time.
This can be a win on programs that do a lot of data movement on
aligned pointers.

A good implementation of memcpy will check lengths and alignments and
do the fastest possible move available on that particular machine.
Typical implementations are something else. Even a good implementation
without compiler assistance requires start up code everytime it is
called to determine what is the fastest move; often the compiler will
have all that information available, but it doesn't often happen that
information is made available to memcpy.

This kind of code is either defense against mediocre memcpy
implementations or a vain belief the programmer is cleverer
than the compiler.
--
SM Ryan http://www.rawbw.com/~wyrmwif/
But I do believe in this.
Jul 24 '06 #10
On Mon, 24 Jul 2006 12:58:09 GMT, Frederick Gotham
<fg*******@SPAM.comwrote in comp.lang.c:
quantumred posted:
unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;


This will work perfectly if:

(1) 4 == sizeof(int)

(2) alignof(char[4]) >= alignof(int)
The C Standard does not provide these guarantees for all platforms and
implementations. What you have is non-portable, platform-specific code.
To be perfectly correct, the C standard does not provide these
guarantees for ANY platform OR implementation.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Jul 25 '06 #11

"Ben Pfaff" <bl*@cs.stanford.eduha scritto nel messaggio
news:87************@benpfaff.org...
Frederick Gotham <fg*******@SPAM.comwrites:
quantumred posted:
unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;
This will work perfectly if:

(1) 4 == sizeof(int)

(2) alignof(char[4]) >= alignof(int)

(3) unsigned int does not have trap representations, etc.
I think It is not sufficient.

(3) unsigned int does not have padding bits

should be preferible.

In presence of padding bits

(*(unsigned int *)a2) can have many representations.

In this case with assignment

*(unsigned int *)a1=*(unsigned int *)a2;

you are not guaranteed to copy all bytes correctly.

--
Giorgio Silvestri

Jul 25 '06 #12
On Mon, 24 Jul 2006 12:58:09 GMT, Frederick Gotham
<fg*******@SPAM.comwrote:
quantumred posted:
unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;


This will work perfectly if:

(1) 4 == sizeof(int)

(2) alignof(char[4]) >= alignof(int)
To be pedantic, alignof (unsigned char [4]) % alignof (unsigned int)
== 0. Although it is clearly expected and normally true that stricter
alignments (if they exist at all) are multiples of all looser ones,
that isn't explicitly required; a perverse (DS9k) implementation could
align char[4] to 3 and int to 5.

To be accurate, alignof(a1) % alignof(int) == 0
and alignof(a2) % alignof(int) . An implementation reasonably could
(and I use one which does) align 'top-level' variables a1 and a2 more
strictly than u_char[4] requires, and in fact sufficient for u_int.
>
The C Standard does not provide these guarantees for all platforms and
implementations. What you have is non-portable, platform-specific code.

It seems to me that the author was aiming to optimise the copying of an
array. I'd probably take a route somewhat akin to the following:

#define DEFINE_SOLE_MEMBER(Type) \
\
struct SoleMember##Type { \
Type obj; \
} /* Usage code provides semi-colon */ \

#define SoleMember(Type) SoleMember##Type
Presumably for C you meant either SoleMember(Type) to expand to
struct SoleMember##Type

or the DEFINE_SOLE_MEMBER to do a typedef like
typedef struct { Type obj; } SoleMember##Type

<OTIn C++ your combination would work. </>
int main()
{
unsigned char a1[4]= {5,10,15,20};
unsigned char a2[4]= {25,30,35,40};

typedef char char4[4];

DEFINE_SOLE_MEMBER(char4);

*(SoleMember(char4)*)a1 = *(SoleMember(char4) const*)a2;
}
(The Standard guarantees that you can cast from a pointer to a struct, to a
pointer to the type of its first member. However, I don't believe it
guarantees the reverse -- so the code might be slightly dubious.)
It does guarantee conversion from _actual_ (and hence correctly
aligned) first member back to the struct. But here of course the issue
is that _a variable of that same type_ may be misaligned. This is only
likely to be needed and happen in practice if the struct contains
other stricter members, but is formally allowed even if it doesn't.

- David.Thompson1 at worldnet.att.net
Jul 31 '06 #13

Jack Klein wrote:
On Mon, 24 Jul 2006 12:58:09 GMT, Frederick Gotham
<fg*******@SPAM.comwrote in comp.lang.c:
quantumred posted:
unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};
>
*(unsigned int *)a1=*(unsigned int *)a2;

This will work perfectly if:

(1) 4 == sizeof(int)

(2) alignof(char[4]) >= alignof(int)
The C Standard does not provide these guarantees for all platforms and
implementations. What you have is non-portable, platform-specific code.

To be perfectly correct, the C standard does not provide these
guarantees for ANY platform OR implementation.
And even if it did, the behaviour would still be
undefined.

Jul 31 '06 #14
Dave Thompson <da*************@worldnet.att.netwrites:
On Mon, 24 Jul 2006 12:58:09 GMT, Frederick Gotham
<fg*******@SPAM.comwrote:
>quantumred posted:
unsigned char a1[4]= { 5,10,15,20};
unsigned char a2[4]= { 25,30,35,40};

*(unsigned int *)a1=*(unsigned int *)a2;


This will work perfectly if:

(1) 4 == sizeof(int)

(2) alignof(char[4]) >= alignof(int)
To be pedantic, alignof (unsigned char [4]) % alignof (unsigned int)
== 0. Although it is clearly expected and normally true that stricter
alignments (if they exist at all) are multiples of all looser ones,
that isn't explicitly required; a perverse (DS9k) implementation could
align char[4] to 3 and int to 5.
[...]

Actually, I don't think it could. int could have an alignment of 5,
but char[4] can't have a required alignment of 3. Given:

char arr[2][4]

the two elements of arr must be adjacent and must each have a size of
4 bytes.

In general, because there can't be gaps between array elements, the
size of a type must be a multiple of its alignment. (The
implementation can adjust the size if necessary to make this happen,
for example by adding padding bits.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Jul 31 '06 #15
On Mon, 31 Jul 2006 07:31:53 GMT, Keith Thompson <ks***@mib.org>
wrote:
Dave Thompson <da*************@worldnet.att.netwrites:
To be pedantic, alignof (unsigned char [4]) % alignof (unsigned int)
== 0. Although it is clearly expected and normally true that stricter
alignments (if they exist at all) are multiples of all looser ones,
that isn't explicitly required; a perverse (DS9k) implementation could
align char[4] to 3 and int to 5.
[...]

Actually, I don't think it could. int could have an alignment of 5,
but char[4] can't have a required alignment of 3. Given:

char arr[2][4]

the two elements of arr must be adjacent and must each have a size of
4 bytes.
Oops, you're right. I didn't think far enough.
In general, because there can't be gaps between array elements, the
size of a type must be a multiple of its alignment. (The
implementation can adjust the size if necessary to make this happen,
for example by adding padding bits.)
Except to character types, or at least unsigned char and thus possibly
plain char. And, by the reasoning above, arrays of them.

But I still maintain in the example upthread int could (perversely)
require an alignment not supplied by char[4].

- David.Thompson1 at worldnet.att.net
Aug 14 '06 #16

Dave Thompson wrote:
On Mon, 31 Jul 2006 07:31:53 GMT, Keith Thompson <ks***@mib.org>
wrote:
Dave Thompson <da*************@worldnet.att.netwrites:
To be pedantic, alignof (unsigned char [4]) % alignof (unsigned int)
== 0. Although it is clearly expected and normally true that stricter
alignments (if they exist at all) are multiples of all looser ones,
that isn't explicitly required; a perverse (DS9k) implementation could
align char[4] to 3 and int to 5.
[...]

Actually, I don't think it could. int could have an alignment of 5,
but char[4] can't have a required alignment of 3. Given:

char arr[2][4]

the two elements of arr must be adjacent and must each have a size of
4 bytes.
Oops, you're right. I didn't think far enough.
In general, because there can't be gaps between array elements, the
size of a type must be a multiple of its alignment. (The
implementation can adjust the size if necessary to make this happen,
for example by adding padding bits.)

Except to character types, or at least unsigned char and thus possibly
plain char. And, by the reasoning above, arrays of them.

But I still maintain in the example upthread int could (perversely)
require an alignment not supplied by char[4].
Are you saying anything more than, eg, char[4] can
require four byte alignment whereas int could allow
alignment of either 0 or 2 mod 4? Certainly the
set of alignments allowed for int must have some
overlap with the set of alignments allowed for
char[4].

Aug 14 '06 #17
en******@yahoo.com writes:
Dave Thompson wrote:
>On Mon, 31 Jul 2006 07:31:53 GMT, Keith Thompson <ks***@mib.org>
wrote:
Dave Thompson <da*************@worldnet.att.netwrites:
To be pedantic, alignof (unsigned char [4]) % alignof (unsigned int)
== 0. Although it is clearly expected and normally true that stricter
alignments (if they exist at all) are multiples of all looser ones,
that isn't explicitly required; a perverse (DS9k) implementation could
align char[4] to 3 and int to 5.
[...]

Actually, I don't think it could. int could have an alignment of 5,
but char[4] can't have a required alignment of 3. Given:

char arr[2][4]

the two elements of arr must be adjacent and must each have a size of
4 bytes.
Oops, you're right. I didn't think far enough.
In general, because there can't be gaps between array elements, the
size of a type must be a multiple of its alignment. (The
implementation can adjust the size if necessary to make this happen,
for example by adding padding bits.)

Except to character types, or at least unsigned char and thus possibly
plain char. And, by the reasoning above, arrays of them.

But I still maintain in the example upthread int could (perversely)
require an alignment not supplied by char[4].

Are you saying anything more than, eg, char[4] can
require four byte alignment whereas int could allow
alignment of either 0 or 2 mod 4? Certainly the
set of alignments allowed for int must have some
overlap with the set of alignments allowed for
char[4].
int could have an alignment of, say, 5. If char[4] required an
alignment of 4, then a union of an int and a char[4] would require an
alignment of at least 20.

But I'm not sure that char[4] can require an alignment stricter than 1
byte. For example, this:

char buf[5];
char (*p)[4] = (char(*)[4])(buf+1);

make p a pointer to a char[4] array that aliases elements 1..4 of buf.
Is this guaranteed to make p a valid pointer?

More generally, may an array of type X have a stricter alignment
requirement than type X itself?

An implementation may, of course, choose to align a char array, or
even a single char object, on, say, a word boundary; the question is
whether it can require such strict alignment.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Aug 14 '06 #18
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
>More generally, may an array of type X have a stricter alignment
requirement than type X itself?
No: that would interfere with the requirement that the address of
a variable of non-aggregate type is equivilent to the address
of an array of length 1 of that type. (If I recall correctly, this
requirement is part of the definition of pointer comparison.)
--
Programming is what happens while you're busy making other plans.
Aug 14 '06 #19

Walter Roberson wrote:
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.orgwrote:
More generally, may an array of type X have a stricter alignment
requirement than type X itself?

No: that would interfere with the requirement that the address of
a variable of non-aggregate type is equivilent to the address
of an array of length 1 of that type. (If I recall correctly, this
requirement is part of the definition of pointer comparison.)
Keith was talking about arrays of length greater than one.

Aug 15 '06 #20

Keith Thompson wrote:
en******@yahoo.com writes:
Dave Thompson wrote:
On Mon, 31 Jul 2006 07:31:53 GMT, Keith Thompson <ks***@mib.org>
wrote:
Dave Thompson <da*************@worldnet.att.netwrites:
To be pedantic, alignof (unsigned char [4]) % alignof (unsigned int)
== 0. Although it is clearly expected and normally true that stricter
alignments (if they exist at all) are multiples of all looser ones,
that isn't explicitly required; a perverse (DS9k) implementation could
align char[4] to 3 and int to 5.
[...]

Actually, I don't think it could. int could have an alignment of 5,
but char[4] can't have a required alignment of 3. Given:

char arr[2][4]

the two elements of arr must be adjacent and must each have a size of
4 bytes.

Oops, you're right. I didn't think far enough.

In general, because there can't be gaps between array elements, the
size of a type must be a multiple of its alignment. (The
implementation can adjust the size if necessary to make this happen,
for example by adding padding bits.)

Except to character types, or at least unsigned char and thus possibly
plain char. And, by the reasoning above, arrays of them.

But I still maintain in the example upthread int could (perversely)
require an alignment not supplied by char[4].
Are you saying anything more than, eg, char[4] can
require four byte alignment whereas int could allow
alignment of either 0 or 2 mod 4? Certainly the
set of alignments allowed for int must have some
overlap with the set of alignments allowed for
char[4].

int could have an alignment of, say, 5. If char[4] required an
alignment of 4, then a union of an int and a char[4] would require an
alignment of at least 20.
My assumption was the earlier context stipulated an
int of size 4. If int were of size 5 then I agree
with your comment. Also note, my comment was only
an example.
But I'm not sure that char[4] can require an alignment stricter than 1
byte. For example, this:

char buf[5];
char (*p)[4] = (char(*)[4])(buf+1);

make p a pointer to a char[4] array that aliases elements 1..4 of buf.
Is this guaranteed to make p a valid pointer?
I believe the Standard does not guarantee p will be valid,
either directly or indirectly. And, to draw the conclusion,
the guarantee of validity would need to be explicit.
More generally, may an array of type X have a stricter alignment
requirement than type X itself?
Yes, I believe it may, provided the array has a defined
array bound that is greater than one.
An implementation may, of course, choose to align a char array, or
even a single char object, on, say, a word boundary; the question is
whether it can require such strict alignment.
Yes; unless there is specific language that shows
such an alignment can't be required, it can be
required. I'm not aware of any such language for
arrays of length greater than one.

Aug 15 '06 #21

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by David Rager | last post: by
20 posts views Thread by j0mbolar | last post: by
3 posts views Thread by glenn | last post: by
3 posts views Thread by Dennis | last post: by
12 posts views Thread by O.B. | last post: by
57 posts views Thread by buuuuuum | last post: by
11 posts views Thread by jois.de.vivre | last post: by
reply views Thread by NPC403 | last post: by
reply views Thread by kermitthefrogpy | last post: by
reply views Thread by zattat | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.