making bytes out of bits

J

James Kuyper

How is this expression legal:
5["abcdef]"


That isn't a syntactically correct expression. I suspect that you have
the last two characters reversed, and that what you're actually
referring to is 5["abcdef"].

The expression a is defined as meaning *(a+b). Therefore, 5["abcdef"]
means *(5+"abcdef"). The string literal "abcdef" has a value that points
to a six-element array of char, containing the elements 'a', 'b', 'c',
'd', 'e', 'f', and '\0'. 5+"abcdef" is an expression whose value is a
pointer to char that points at the sixth element of that array.
*(5+"abcdef") dereferences that pointer, and therefore has a value of '\0'.
 
J

James Kuyper

George said:
On Tue, 09 Dec 2008 18:12:31 -0800, Barry Schwarz wrote: ....
#include <stdio.h>

int main(void)
{
char a[40];
char b[8][5];


char *p1;
char (*p2)[5];

int i;
char c;

for (i=60; i = 60 + 40 ; ++ i)
{
a[i-60] = i;
}

I strongly suspect that you mean "i==60+40". The way you wrote it, the
loop condition always has a value of 100, which is non-zero, so the loop
never terminates.
One is legal; the other is not? They vary by one degree of indirection?
The drapes don't match the curtains?

p1++ increase the position that p1 points at by one 'char', since p1
points at a char. p2++ increases the position that p2 points at by one
array of 5 chars, since p2 points at an array of 5 chars.
 
G

George

char a[40]
char b[8][5];
char *p1;
char (*p2)[5];
p1 = a; /* legal because a is converted to char* */
p1 = b; /* illegal because b is converted to char(*)[5] */
p2 = b; /* legal as noted above */
p1 = (char*)b; /* legal because the cast changes the type */

Well, I tried to populate these arrays, but I get no output:

Since the compiler told you the code was broken, why did you even
bother to execute it?

And why are you repeatedly changing the topic of discussion but not
starting a new thread. You deliberately deleted the quote from your
message which asked the question my code tried to respond to. Your
question had nothing to do with the you posted below.
#include <stdio.h>

int main(void)
{
char a[40];
char b[8][5];


char *p1;
char (*p2)[5];

int i;
char c;

for (i=60; i = 60 + 40 ; ++ i)

How many times do you think this loop executes. Hint: it is not 40.
{
a[i-60] = i;

As a result of the error above, this statement invokes undefined
behavior.
}

for(i = 0; i = 40; ++ i)
{
putchar(a);
}

putchar('\n');




p1 = a; /* legal because a is converted to char* */
p1 = b; /* illegal because b is converted to char(*)[5] */
p2 = b; /* legal as noted above */
p1 = (char*)b; /* legal because the cast
changes the type */
return 0;
}
// gcc -Wall schwartz2.c -o x.exe

This compiles with the following warnings, but hangs.


C:\MinGW\source> gcc -Wall schwartz2.c -o x.exe


I would hate to my name associated with such abominable code. But
since you misspelled my name I don't have to worry about it.
schwartz2.c: In function `main':
schwartz2.c:17: warning: suggest parentheses around assignment used as
truth val

Be honest. You are just trolling. What other reason do you have for
ignoring the compiler identifying the problems in your code.
ue
schwartz2.c:22: warning: suggest parentheses around assignment used as
truth val
ue
schwartz2.c:33: warning: assignment from incompatible pointer type
schwartz2.c:15: warning: unused variable `c'

C:\MinGW\source>

I usually populate integer arrays by assigning them to the index of a loop
that runs the range. I thought it would be a good thing to avoid the first
32 chars and start with sixty instead, which is zero on my implementation.

ASCII uses 0x30 and EBCDIC uses 0xf0. I once worked with a Hazeltine
display system where '0' was 0x60 but '1' was 0x62 so it could not be
a C system. Could you give us the brand name or the name of the
coding convention that uses 0x3c for '0' as you claim.
??



One is legal; the other is not? They vary by one degree of indirection?
The drapes don't match the curtains?

Surely you jest. Both expressions are perfectly legal if the pointer
in question has been assigned a valid non-NULL value.

Maybe you and Bill Cunningham could form a club and tutor each other.


Yes Barry, I changed the equals to less than and now have a program I
understand. Did my complete lack of snipping above appeal to your
sensibilities (rhetorical question, see number 1)?

1) Do not reply to me again.
2) Schwartz means "black".
3) If Bill's a reasonable human being, I would much rather endure his
company as opposed to yours.
4) You're the size of my average bowel movement.
--
George

Today we affirm a new commitment to live out our nation's promise through
civility, courage, compassion and character.
George W. Bush

Picture of the Day http://apod.nasa.gov/apod/
 
G

George

George said:
On Tue, 09 Dec 2008 18:12:31 -0800, Barry Schwarz wrote: ...
#include <stdio.h>

int main(void)
{
char a[40];
char b[8][5];


char *p1;
char (*p2)[5];

int i;
char c;

for (i=60; i = 60 + 40 ; ++ i)
{
a[i-60] = i;
}

I strongly suspect that you mean "i==60+40". The way you wrote it, the
loop condition always has a value of 100, which is non-zero, so the loop
never terminates.

I got that. In the meantime, my desire to use the inferior tool which is
the C Programming Language for array manipulation has waned. Here's how
you do it in fortran:

integer, parameter :: outfile = 51
character(len=100) :: line
integer :: seqnum, eof,i, bits_needed
integer :: bit_count, ibuf, val
integer(1) :: out(100000)
character :: c*1


! main control

open(unit=50,file='george.txt',form='formatted')


! initialize counters
bit_count = 0
ibuf = 0
val = 0

line_loop: &
do
read (50,*,iostat=eof) seqnum, line
if (eof /= 0) exit line_loop
char_loop: &
do i = 1, len_trim (line)
c = line(i:i)
if (c /= '0' .and. c /= '1') cycle char_loop
! ignore non-data chars
! Pack each 0 or 1 into the next byte, order MSB first.
val = val * 2 ! shift accumulator left 1 bit
if (c == '1') val = val + 1 ! insert new bit on right
bit_count = bit_count + 1
! When next byte is complete, add to buffer.
if (bit_count == 8) then
ibuf = ibuf + 1 ! advance buffer pointer
out(ibuf) = val ! convert for single byte output
if (val >= 128) out(ibuf) = val - 256 ! handle negs
bit_count = 0 ! reset accumulator for next byte
val = 0
end if
end do char_loop
end do line_loop


! Handle incomplete final byte. Pad and add to buffer.

if (bit_count > 0) then
bits_needed = 8 - bit_count
val = val * (2 ** bits_needed) ! shift left, zero pad on right
ibuf = ibuf + 1 ! advance buffer pointer
out(ibuf) = val ! convert for single byte output
if (val >= 128) out(ibuf) = val - 256 ! handle negatives
end if

! Write to output file.

open (outfile, file='bin2.dat', access='direct', recl=ibuf, &
action='write', status='replace')
write (outfile, rec=1) out(1:ibuf) ! write complete buffer
close (outfile)

print *, 'Number of bytes written = ', ibuf

! clean up and exit

close(unit=50)
endprogram

! g95 dave3.f03 -o x.exe

BTW, I don't know who dave is.

p1++ increase the position that p1 points at by one 'char', since p1
points at a char. p2++ increases the position that p2 points at by one
array of 5 chars, since p2 points at an array of 5 chars.

Thanks. This arcane, useless, cryptic, irrelevant, stupid, parochial
formulation was brought up by Barry, with whom I've had a falling out.
I'll take this as my nod to leave. Thanks for your comment and Merry
Christmas.
--
George

The United States and our allies are determined: we refuse to live in the
shadow of this ultimate danger.
George W. Bush

Picture of the Day http://apod.nasa.gov/apod/
 
P

Phil Carmody

George said:
[code elided and paragraphs reordered for thematic reasons]
FAQ 6.2 "But I heard that char a[] was identical to char *a"
then FAQs 6.3, 6.4, 6.8... well pretty much the whole section

I got to that last night. It certainly makes for a better read as a hard
copy next to a fire. Given that I'm burning books based on lack of
relevacne to C, I think Steve's work will survive the heating season.
read sections 5.7 and 5.9

I think this is getting really close to what I'm not getting here.

q1) I don't understand the first example in 5.9. B is declared as
int *b[10];
and b[3][4] is syntactically legal. What gives? Is twelve less than or
equal to ten?

Where on earth did you get the 'twelve' from in the above sentence?
There is no 12 that is in any way relevant to the situation you
describe. Please get a book and learn the basics of C.

Phil
 
L

Lew Pitcher

q1) I don't understand the first example in 5.9. B is declared as
int *b[10];
and b[3][4] is syntactically legal. What gives? Is twelve less than or
equal to ten?

Where on earth did you get the 'twelve' from in the above sentence?
There is no 12 that is in any way relevant to the situation you
describe. Please get a book and learn the basics of C.

I haven't been following this thread, but, I can see where George got 12
from, and why he asks his question.

If
b[3][4]
is syntatically legal (as george says), then it implies that the b array has
at least 12 elements (3 * 4 = 12). Actually, that addressing implies that
the array has at least 20 elements, since C uses zero-based array
subscripting (the [3] would imply that there were at least 4 major ordinal
arrays, and the [4] would imply that there were at least 5 minor ordinal
elements, and 4 * 5 = 20).

Otoh, the array is declared as
int *b[10];
giving the b array a complement of 10 elements.

Thus, the question "Is twelve less than or equal to ten?". The 12 comes from
the calculation of the minimum number of elements needed to satisfy the
b[3][4] expression, and the 10 comes from the maximum number of elements
declared for the array.



--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
P

Phil Carmody

Lew Pitcher said:
q1) I don't understand the first example in 5.9. B is declared as
int *b[10];
and b[3][4] is syntactically legal. What gives? Is twelve less than or
equal to ten?

Where on earth did you get the 'twelve' from in the above sentence?
There is no 12 that is in any way relevant to the situation you
describe. Please get a book and learn the basics of C.

I haven't been following this thread, but, I can see where George got 12
from, and why he asks his question.

If
b[3][4]
is syntatically legal (as george says), then it implies that the b array has
at least 12 elements (3 * 4 = 12).


Wrong.
int b[2][2];
foo(b[3][4]);
is *syntactically* legal. There's more to the interpretation
of computer languages than just the syntax.
Actually, that addressing implies that
the array has at least 20 elements, since C uses zero-based array
subscripting (the [3] would imply that there were at least 4 major ordinal
arrays, and the [4] would imply that there were at least 5 minor ordinal
elements, and 4 * 5 = 20).

That's one reason why 12 is absolutely nothing to do with
the question in hand, certainly.

Wait a second, were you trying to take a contrary stance to me?
If so, why have you just supported my argument that the number 12
is irrelevant?
Otoh, the array is declared as
int *b[10];
giving the b array a complement of 10 elements.

Thus, the question "Is twelve less than or equal to ten?". The 12 comes from
the calculation of the minimum number of elements needed to satisfy the
b[3][4] expression

False, as you proved above. If you're going to contradict yourself
can you please ensure you don't accidentally agree with me with any
of the things that you say, so that way I can more easily distance
myself from your random gibberings?

However, you're not just wrong, you're also just plain wrong.
b[3][4] can be a perfectly valid way of accessing an int even
if there's only been allocation for 5 ints.
, and the 10 comes from the maximum number of elements
declared for the array.

And of course I didn't ask about the 10.

Phil
 
J

jameskuyper

Lew said:
q1) I don't understand the first example in 5.9. B is declared as
int *b[10];
and b[3][4] is syntactically legal. What gives? Is twelve less than or
equal to ten?

Where on earth did you get the 'twelve' from in the above sentence?
There is no 12 that is in any way relevant to the situation you
describe. Please get a book and learn the basics of C.

I haven't been following this thread, but, I can see where George got 12
from, and why he asks his question.

If
b[3][4]
is syntatically legal (as george says), then it implies that the b array has
at least 12 elements (3 * 4 = 12).

As an array declaration, that would be true. Since no such declaration
appears in the program, it's completely irrelevant.

As an expression following the given declaration, b[3][4] implies
nothing of the sort. The declaration of b implies that there are 10
pointers to int. The expression b[3][4] implies that the fourth such
pointer has been set to point at an array of at least 5 integers. It
doesn't tell you whether any of the other 9 pointers have even been
set to a value, much less whether or not that value is null, and if it
it not null, you don't know anything about the length of the array
that it points at. Each pointer could point at an array of a different
length. The number 12 has no part to play in any of this.
 
K

Keith Thompson

Azazel said:
b[3][4] obviously has two [] operators, so there are four
possibilities:

1. b is a pointer, and b[3] is also a pointer.
b must therefore be a pointer to pointer, such as a char**.
char **b;

2. b is a pointer to an array.
char *b[10];

3. b is an array of pointers.
char (*b)[10];

4. b is an array of arrays, i.e., a two-dimensional array.
char b[5][6];

Are 2 & 3 correct? Surely

char *b[10];

is an array of 10 pointers-to-char and

char (*b)[10]

is a pointer to array-of-10-chars?

D'oh! You're right, of course. (I rearranged the 4 cases but failed
to rearrange the descriptions.)
 
J

James Kuyper

Joe said:
James Kuyper wrote: ....
5["abcdef"] means *(5+"abcdef"). The string literal "abcdef" has a
value that points to a six-element array of char, containing the
elements 'a', 'b', 'c', 'd', 'e', 'f', and '\0'. 5+"abcdef" is an
expression whose value is a pointer to char that points at the sixth
element of that array. *(5+"abcdef") dereferences that pointer, and
therefore has a value of '\0'.

You might find *(5+"abcdef") is 'f'.

Did I ever say that I knew how to count? :-{
 
J

James Kuyper

George said:
....
I got that. In the meantime, my desire to use the inferior tool which is
the C Programming Language for array manipulation has waned. Here's how
you do it in fortran:

It's not clear to me what your criticism of C's array manipulation is. I
vaguely remember Fortran array-handling features that are slightly
more convenient in some circumstances than their C counterparts, but I
don't see you make any use of such features in this program.
integer, parameter :: outfile = 51
character(len=100) :: line
integer :: seqnum, eof,i, bits_needed
integer :: bit_count, ibuf, val
integer(1) :: out(100000)
character :: c*1


! main control

open(unit=50,file='george.txt',form='formatted')


! initialize counters
bit_count = 0
ibuf = 0
val = 0

line_loop: &
do
read (50,*,iostat=eof) seqnum, line
if (eof /= 0) exit line_loop
char_loop: &
do i = 1, len_trim (line)
c = line(i:i)
if (c /= '0' .and. c /= '1') cycle char_loop
! ignore non-data chars
! Pack each 0 or 1 into the next byte, order MSB first.
val = val * 2 ! shift accumulator left 1 bit
if (c == '1') val = val + 1 ! insert new bit on right
bit_count = bit_count + 1
! When next byte is complete, add to buffer.
if (bit_count == 8) then
ibuf = ibuf + 1 ! advance buffer pointer
out(ibuf) = val ! convert for single byte output
if (val >= 128) out(ibuf) = val - 256 ! handle negs
bit_count = 0 ! reset accumulator for next byte
val = 0
end if
end do char_loop
end do line_loop


! Handle incomplete final byte. Pad and add to buffer.

if (bit_count > 0) then
bits_needed = 8 - bit_count
val = val * (2 ** bits_needed) ! shift left, zero pad on right
ibuf = ibuf + 1 ! advance buffer pointer
out(ibuf) = val ! convert for single byte output
if (val >= 128) out(ibuf) = val - 256 ! handle negatives
end if

! Write to output file.

open (outfile, file='bin2.dat', access='direct', recl=ibuf, &
action='write', status='replace')
write (outfile, rec=1) out(1:ibuf) ! write complete buffer
close (outfile)

print *, 'Number of bytes written = ', ibuf

! clean up and exit

close(unit=50)
endprogram

! g95 dave3.f03 -o x.exe

Here's an idiomatic translation into C. It's somewhat longer than your
Fortran version, but that's mainly due to some improvements in error
handling. Could you please identify which aspects of this program
demonstrate that C is an "inferior tool ... for array manipulation"?


#include <stdio.h>
#include <stdlib.h>
#define INNAME "george.txt"
#define OUTNAME "bin2.dat"
#define MAX_SIZE 100000

int main(void)
{
char buffer[128];
int bit_count=0, ibuf=0, val=0;
signed char out[MAX_SIZE];
FILE *infile = fopen(INNAME, "r");
FILE *outfile;
int retval = EXIT_SUCCESS;

if(infile==NULL)
{
perror(INNAME);
return EXIT_FAILURE;
}
while(retval == EXIT_SUCCESS &&
fgets(buffer, sizeof buffer, infile)==buffer)
{
int segnum, offset;
int fields = sscanf(buffer, "%d%n", &segnum, &offset);

if(fields != 1)
{
fprintf(stderr, "sscanf(\"%s\") returned %d\n", buffer,
fields);
retval = EXIT_FAILURE;
break;
}
for(char *p = buffer+offset; *p; p++)
{
if(*p != '0' && *p != '1')
continue;
if(ibuf == MAX_SIZE-1)
{
fprintf(stderr, "segnum:%d - Array full", segnum);
retval = EXIT_FAILURE;
break;
}
val *= 2;
if(*p == '1')
val++;
bit_count++;
if(bit_count==8)
{
ibuf++;
out[ibuf] = val - (val >= 256 ? 256 : 0);
bit_count = 0;
val = 0;
}
}
}
if(ferror(infile))
{
perror(INNAME);
return EXIT_FAILURE;
}
fclose(infile);

if(bit_count)
{
int bits_needed = 8 - bit_count;
val <<= bits_needed;
ibuf++;
out[ibuf] = val - (val >= 256 ? 256 : 0);
}

outfile = fopen(OUTNAME, "wb");
if(outfile==NULL)
{
perror(OUTNAME);
return EXIT_FAILURE;
}
if(fwrite(out, sizeof out[0], ibuf+1, outfile)!=ibuf+1)
{
perror(OUTNAME);
retval = EXIT_FAILURE;
}
fclose(outfile);

return retval;
}
Thanks. This arcane, useless, cryptic, irrelevant, stupid, parochial
formulation was brought up by Barry, with whom I've had a falling out.

Now, don't hold back; tell us how you really feel. :)

Most of those adjectives are subjective value judgments, and I'm willing
to discount them by considering the source of those judgments. However,
"irrelevant" is objectively wrong. That "formulation" is very directly
relevant to the question of why an array of 8 arrays of 5 chars is
different from an array of 40 characters. Given:

char twod[8][5];
char oned[40];
char *p1;
char (*p2)[5];

Then the following statements are permitted:

p1 = twod[3] + 2;
p1 = oned + 17;
p2 = twod + 3;
p1 = *p2 + 2;

However, in none of those cases could you replace p1 with p2, or vice
versa. Nor could you replace oned with twod, or vice versa. When you
truly understand why, the C language will suddenly seem a lot less
arcane and cryptic.
 
D

David Thompson

George wrote:
char a[40];
int i;
char c;

for (i=60; i = 60 + 40 ; ++ i)
{
a[i-60] = i;
}

I strongly suspect that you mean "i==60+40". The way you wrote it, the
loop condition always has a value of 100, which is non-zero, so the loop
never terminates.
Rather i < 60+40, or perhaps equivalently but less clearly != . == is
initially false, and never executes. As already noted = runs off the
end of the array and invokes Undefined Behavior which is worse.
 
D

David Thompson

It's not clear to me what your criticism of C's array manipulation is. I
vaguely remember Fortran array-handling features that are slightly
more convenient in some circumstances than their C counterparts, but I
don't see you make any use of such features in this program.
Classic FORTAN (<=77, it was allcaps) was generally a little more
convenient. Fortran >= 90 adds major new array features that are
majorly better for certain things, particularly ones that come up in
(modern) science and engineering. But not in George's example.

Aside: integer kind 1 is not even required to exist in standard
Fortran, nor to be one-byte; both are implementation dependent,
although _some_ one-byte integer kind seems to be widespread.
C does require 'signed char' by that name and least 8 bits.
Neither Fortran nor C strictly guarantees an array of 100k bytes,
although any system today with a conforming (or just serious) compiler
does allow it.

I left the prior code for comparison if needed, although I'm not
commenting on the rest of it. Skip a ways ...
Here's an idiomatic translation into C. It's somewhat longer than your
Fortran version, but that's mainly due to some improvements in error
handling. Could you please identify which aspects of this program
demonstrate that C is an "inferior tool ... for array manipulation"?
I don't see much 'idiomatic' here, except the pointer-scan-string;
other than that I'd call it nearly a literal translation.
The error handling you quite properly added in C would usually (though
not strictly always) be handled automatically by the Fortran compiler,
so I don't think that really counts as an improvement; indeed the
increased clutter is arguably a small disadvantage of C.
#include <stdio.h>
#include <stdlib.h>
#define INNAME "george.txt"
#define OUTNAME "bin2.dat"
#define MAX_SIZE 100000

int main(void)
{
char buffer[128];
int bit_count=0, ibuf=0, val=0;
signed char out[MAX_SIZE];
FILE *infile = fopen(INNAME, "r");
FILE *outfile;
int retval = EXIT_SUCCESS;

if(infile==NULL)
{
perror(INNAME);
return EXIT_FAILURE;
}
while(retval == EXIT_SUCCESS &&
fgets(buffer, sizeof buffer, infile)==buffer)
{
int segnum, offset;
int fields = sscanf(buffer, "%d%n", &segnum, &offset);

if(fields != 1)
{
fprintf(stderr, "sscanf(\"%s\") returned %d\n", buffer,
fields);
retval = EXIT_FAILURE;
break;
}

Your handling of too-long input lines/records is slightly different
from his, but both are, ahem, suboptimal, so I'll call that minor.
for(char *p = buffer+offset; *p; p++)
{
if(*p != '0' && *p != '1')
continue;
if(ibuf == MAX_SIZE-1)
{
fprintf(stderr, "segnum:%d - Array full", segnum);
retval = EXIT_FAILURE;
break;
}
val *= 2;
if(*p == '1')
val++;

To be more idiomatic I would use <<1 instead of *2, and probably |1
instead of +1. Bitwise is more convenient in C than in Fortran, and
this really is bit manipulation.
bit_count++;
if(bit_count==8)
{
ibuf++;
out[ibuf] = val - (val >= 256 ? 256 : 0);

Should be >=128 (as he had) for signed-8-bit.
More idiomatic: use unsigned char [], and don't need the correction.
Increment ibuf should be _after_ the store for (zero-origin) C.
bit_count = 0;
val = 0;
}
}
}
if(ferror(infile))
{
perror(INNAME);
return EXIT_FAILURE;
}
fclose(infile);

if(bit_count)
{
int bits_needed = 8 - bit_count;
val <<= bits_needed;
ibuf++;
out[ibuf] = val - (val >= 256 ? 256 : 0);

Same again.
}

outfile = fopen(OUTNAME, "wb");
if(outfile==NULL)
{
perror(OUTNAME);
return EXIT_FAILURE;
}
if(fwrite(out, sizeof out[0], ibuf+1, outfile)!=ibuf+1)

Given the corrections above, not +1.
Alternatively, start ibuf at -1, increment before (both) stores, and
use ibuf+1 for the write. But that just looks ugly to me.
{
perror(OUTNAME);
retval = EXIT_FAILURE;
}
fclose(outfile);
Should also check fclose() and handle error; it CAN happen.
return retval;
}
<snip other>
 
J

James Kuyper

David said:
Classic FORTAN (<=77, it was allcaps) was generally a little more

FORTRAN 77 is the most recent version I've actually written any
significant amount of code for. I've modified some Fortran 90 programs
(without breaking them, and even achieving the intended effect!), but I
can't say I really know anything significant about how it differs from
FORTRAN 77; I just know that it does differ, very significantly.
convenient. Fortran >= 90 adds major new array features that are
majorly better for certain things, particularly ones that come up in
(modern) science and engineering. But not in George's example. ....

Aside: integer kind 1 is not even required to exist in standard
Fortran, nor to be one-byte; both are implementation dependent,
although _some_ one-byte integer kind seems to be widespread.
C does require 'signed char' by that name and least 8 bits.
Neither Fortran nor C strictly guarantees an array of 100k bytes,
although any system today with a conforming (or just serious) compiler
does allow it. ....
I don't see much 'idiomatic' here, except the pointer-scan-string;
other than that I'd call it nearly a literal translation.
The error handling you quite properly added in C would usually (though
not strictly always) be handled automatically by the Fortran compiler,
so I don't think that really counts as an improvement; indeed the
increased clutter is arguably a small disadvantage of C.

As I've said elsewhere, my Fortran knowledge is both rusty and
out-of-date. Thanks for your comments and corrections.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top