By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,230 Members | 2,436 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,230 IT Pros & Developers. It's quick & easy.

Question on "if" statements...

P: n/a
Hello all,

I was wondering if there were some sort of limitations on the "if"
statement? I'm writing a program which needs to check a bunch of
conditions all at the same time (basically). And I'm pretty sure the
rest of the program is working just fine. The only thing I could think
might be wrong is that the if statement can only hold so many values in
itself? Let me show what I'm doing:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

My problem is that "do_stuff" is never executed. There are 30 different
tables of int's I'm checking against up there. I could use more in the
future, and for the purposes of my program, I don't want to use less. I
know that do_stuff should be executed because I have run test cases
where it should have been run. But it just keeps goin to the "else"
statement. I'm probably way off base thinking C is the problem. If you
want to know about my setup here it is:
WinXP, P4 1.8, Compiler: DJGPP using gcc v3.0.3

So, am I expecting too much out of the if statement? Am I using the if
statement incorrectly up there? Any advice or help in this regard is
greatly appreciated.

-David C.
Nov 14 '05 #1
Share this Question
Share on Google+
35 Replies


P: n/a

On Mon, 26 Apr 2004, David Cleaver wrote:

I was wondering if there were some sort of limitations on the "if"
statement? I'm writing a program which needs to check a bunch of
conditions all at the same time (basically). And I'm pretty sure the
rest of the program is working just fine. The only thing I could think
might be wrong is that the if statement can only hold so many values in
itself?
There is some limitation given by the official standard in that
it specifies a "minimal limit" for the depth of expressions (if I
recall correctly). That is, the Standard says how many "ands" an
'if' statement *must* be able to hold; but any decent implementation
will be able to handle as many as you can throw at it (up to the
available memory on your machine).
Let me show what I'm doing:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

My problem is that "do_stuff" is never executed.


Have you considered the possibility that the body of the 'if' is
never executed because the big complicated condition is, in fact,
*false*? Have you tried running the 'if' statement in a program
in which "table001..030" and "b" are entirely filled with 0x1f
values? What values are stored in those tables during the run of
your current program?

[OT: And why do you need so many tables anyway, and why not use
a "for" loop to check all of them, rather than hard-code the
number of tables into your program?]

-Arthur
Nov 14 '05 #2

P: n/a
David Cleaver wrote:
Let me show what I'm doing:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&

[...]

The formatting is a bit misleading. This is parsed as:

if (table001[n[0]][x[0]>>5] & (b[x[0]&0x1f] != 0) &&
....

Ralf
Nov 14 '05 #3

P: n/a

"David Cleaver" <wr*****@morpheus.net> wrote in message
news:40***************@morpheus.net...

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();


Are you REALLY sure that this is the test you want to be performing?

You have a really long expression containing three different operators (&,
!=, &&) used many times each. Since you have not told the compiler how to
group them, you are basically choosing to let the compiler make the decision
for you. This is frequently not a good idea.



Nov 14 '05 #4

P: n/a
"David Cleaver" <wr*****@morpheus.net> wrote in message
news:40***************@morpheus.net...
I was wondering if there were some sort of limitations on the "if"
statement? I'm writing a program which needs to check a bunch of
conditions all at the same time (basically). And I'm pretty sure the
rest of the program is working just fine. The only thing I could think
might be wrong is that the if statement can only hold so many values in
itself? Let me show what I'm doing:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();


First, the order of operations isn't clear in your expression. As a rule of
thumb, if the reader needs to look up the rules to figure out what an
expression does, you should add parens to make it clear what you intended.
Second, judicious use of spaces makes complex expressions more readable.
Third, the test against zero is unnecessary since that's implied with
logical operators.

if ( ( table001[n[0]][x[0]>>5] & b[x[0]&0x1f] ) &&
( table002[n[1]][x[1]>>5] & b[x[1]&0x1f] ) &&
( table003[n[2]][x[2]>>5] & b[x[2]&0x1f] ) &&
... &&
( table030[n[29]][x[29]>>5] & b[x[29]&0x1f] ) )
{
do_stuff();
}//end if
else do_other_stuff();

I don't know if this code is any more correct, but it's a lot easier to read
and debug, which others (and you, later on) will appreciate.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin

Nov 14 '05 #5

P: n/a
William L. Bahn wrote:

"David Cleaver" <wr*****@morpheus.net> wrote in message
news:40***************@morpheus.net...

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();


Are you REALLY sure that this is the test you want to be performing?

You have a really long expression containing three different operators (&,
!=, &&) used many times each. Since you have not told the compiler how to
group them, you are basically choosing to let the compiler make the
decision for you.


The OP is have the *language* make the decision for them - C has a
defined "order of precedence" [1]. Having lots of conditions separated
by && should be no problem at all.

On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y". [Well, actually,
I wouldn't write a monster expression with 30 lines in it embedded in
an if-expression at all, but that's a separate issue.]

[1] defined implicitly by the grammar in the Standard, but expressible
as precedence order.

[2] certain.

--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html
Nov 14 '05 #6

P: n/a
Chris Dollin <ke**@hpl.hp.com> wrote:
On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y".


No, you wouldn't; those two expressions can have different values if Y
is non-zero, but not equal to 1. For example, if X==3 and Y==2, the
first expression has the value 1, and the second the value 2. More
importantly to the OP, if X==Y==2, the second expression still has the
value 2, but the first expression now is 0...

Richard
Nov 14 '05 #7

P: n/a
Richard Bos wrote:
Chris Dollin <ke**@hpl.hp.com> wrote:
On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y".


No, you wouldn't; those two expressions can have different values if Y
is non-zero, but not equal to 1. For example, if X==3 and Y==2, the
first expression has the value 1, and the second the value 2. More
importantly to the OP, if X==Y==2, the second expression still has the
value 2, but the first expression now is 0...


That's the point - I believe that the OP wrote "X & Y != 0" and *meant*
"(X & Y) != 0", which can be written as "X & Y" in conditional context
with the same effect, where it avoids all questions of the relative
precedence of & and !=. Hence "in this case".

--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html
Nov 14 '05 #8

P: n/a
Chris Dollin (== me) wrote:
The OP is have the *language* make the decision for them - C has a
defined "order of precedence" [1]. Having lots of conditions separated
by && should be no problem at all.


Erm, in my haste I did not make it clear that one should still
write expressions for clarity - there's a difference between knowing
the C precedence levels, assuming the reader will know them, and
writing for the IOCC.

--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html
Nov 14 '05 #9

P: n/a


Chris Dollin wrote:

William L. Bahn wrote:

David Cleaver wrote:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

Are you REALLY sure that this is the test you want to be performing?

You have a really long expression containing three different operators (&,
!=, &&) used many times each. Since you have not told the compiler how to
group them, you are basically choosing to let the compiler make the
decision for you.


The OP is have the *language* make the decision for them - C has a
defined "order of precedence" [1]. Having lots of conditions separated
by && should be no problem at all.

On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y". [Well, actually,
I wouldn't write a monster expression with 30 lines in it embedded in
an if-expression at all, but that's a separate issue.]


Thank you very much. I never thought about there being a precedence
issue. I've fixed my code to better reflect what I was doing. [And I
was wanting (x & y), not x & (y != 0), I've changed it all to be of the
form (x & y) && ...]

May I ask, without making those tables 3-dimensional, how could I make
that code segment look better? Someone earlier in this thread mentioned
putting it into a for loop, but I can't see how that'd be possible with
30 different tables.

Anyway, I wanted to thank everyone for their suggestions so far. I'm
really glad a place like this exists where people can come for help.
Thanks again.

-David C.

[1] defined implicitly by the grammar in the Standard, but expressible
as precedence order.

[2] certain.

--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html

Nov 14 '05 #10

P: n/a

"Chris Dollin" <ke**@hpl.hp.com> wrote in message
news:c6**********@murdoch.hpl.hp.com...
William L. Bahn wrote:

"David Cleaver" <wr*****@morpheus.net> wrote in message
news:40***************@morpheus.net...

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

Are you REALLY sure that this is the test you want to be performing?

You have a really long expression containing three different operators (&, !=, &&) used many times each. Since you have not told the compiler how to group them, you are basically choosing to let the compiler make the
decision for you.


The OP is have the *language* make the decision for them - C has a
defined "order of precedence" [1].


The compiler is the one that is making the decision as the compiler is the
one that is compiling the code. I'm not saying that the compiler has any
choice in the decision it makes - and I understand the point you are making.
Please recognize that just saying something like "the compiler is making the
decision" is anthropomorphisizing (sp?) to begin with and the main point is
not who (or what) is making the decision but rather that the OP is NOT
making the decision.
Having lots of conditions separated
by && should be no problem at all.


Really? So something like

if( a || b && c || d )

should present no difficulties and compile the way that it was most likely
meant?


Nov 14 '05 #11

P: n/a

"Richard Bos" <rl*@hoekstra-uitgeverij.nl> wrote in message
news:40*****************@news.individual.net...
Chris Dollin <ke**@hpl.hp.com> wrote:
On the other hand, I'm pretty sure [2] that "X & Y != 0", applying that
order of precedence, groups as "X & (Y != 0)". <fx:flappingPages/> Yes.

In this case, I'd just write the expression as "X & Y".


No, you wouldn't; those two expressions can have different values if Y
is non-zero, but not equal to 1. For example, if X==3 and Y==2, the
first expression has the value 1, and the second the value 2. More
importantly to the OP, if X==Y==2, the second expression still has the
value 2, but the first expression now is 0...


I think he is saying that

"X & Y"

would produce the same results that were almost certainly intended by

"X & Y !=0"

had the OP used parens to make it explicit

"(X & Y) != 0"


Nov 14 '05 #12

P: n/a
David Cleaver <wr*****@morpheus.net> wrote:
I'm writing a program which needs to check a bunch of
conditions all at the same time (basically).

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

My problem is that "do_stuff" is never executed. There are 30 different
tables of int's I'm checking against up there.


Others have pointed out the reason this code doesn't work. But I cannot
think of a reason why you do not go:

int i;
for (i = 0; i < 30; ++i)
if (table[i][n[i]][x[i]>>5] & b[x[i]&0x1f])
break;
if (i == 30)
do_stuff();
else
{
printf("failed on test %d", i); /* if needed */
do_other_stuff();
}

In case you didn't like this for runtime-speed reasons, note that
this is at least as fast as your version
(your version unoptimised is slow because there are 5 array index
lookups on each line, whereas even the worst compiler will optimise
the loop to be incrementing 1 or 2 pointers, with fixed offsets
from that pointer. This will work even better if n, x, and b, are
all the same size of object).

If it isn't convenient to have table[] instead of table001, table002 etc.
from the start, then you could set up an array of pointers (you'd only
have to do this once ever).

Finally, note that n[], x[], and b[] should all be unsigned types,
unless you're really sure of yourself (it's easy to get unexpected
behaviour when doing bitwise operations on signed types).
Nov 14 '05 #13

P: n/a


Old Wolf wrote:

David Cleaver wrote:
I'm writing a program which needs to check a bunch of
conditions all at the same time (basically).

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
do_stuff();
}//end if
else do_other_stuff();

My problem is that "do_stuff" is never executed. There are 30 different
tables of int's I'm checking against up there.
Others have pointed out the reason this code doesn't work. But I cannot
think of a reason why you do not go:

int i;
for (i = 0; i < 30; ++i)
if (table[i][n[i]][x[i]>>5] & b[x[i]&0x1f])
break;
if (i == 30)
do_stuff();
else
{
printf("failed on test %d", i); /* if needed */
do_other_stuff();
}


Thats the opposite of what I want to do, I want n[] and x[] to pass all
of the if tests. I think it should be "if (...) continue; else break;"
right? Anyway, I understand what you are saying, but please read on.

In case you didn't like this for runtime-speed reasons, note that
this is at least as fast as your version
(your version unoptimised is slow because there are 5 array index
lookups on each line, whereas even the worst compiler will optimise
the loop to be incrementing 1 or 2 pointers, with fixed offsets
from that pointer. This will work even better if n, x, and b, are
all the same size of object).
Yes, right now n, x, and b are all arrays of ints. I want this to be as
fast as possible because I'm using it for math applications.

For any given run of the program, each n[k] will be the same, but x[k]
will change as the program runs. So I should probably turn those n's
into constants? And since x[k] is changing I can't use a constant
there, or even on b since it depends on x. BTW, my b array is what I'm
using to see if a particular bit is turned on or not. Is there a better
way to do this? Like maybe:
table[][] & (1<<(32 - (x[i]&0x1f) - 1))?
instead of:
table[][] & b[x[i]&0x1f]
I don't know which would be faster/better.

Is this even an appropriate topic for this forum? I don't know where
else to look to ask about writing programs in C AND making them fast.
If this isn't the right spot, could someone please let me know where
would be better? If its ok, then read on below.

If it isn't convenient to have table[] instead of table001, table002 etc.
from the start, then you could set up an array of pointers (you'd only
have to do this once ever).
Ummm, how would I set up an array of pointers? Is that allowed? I
thought all the arrays had to be the same size? And all my tables are
of different sizes. Would the array of pointers look like this:
int *table;
table = (int *) malloc( 30 * sizeof(int));
table[0] = &table001;
table[1] = &table002;
....
Or would you do it a different way? I've never set up an array of
pointers to other arrays before. At least, not where all the other 2D
arrays are of differing sizes. Now that I think about it, since its an
array of pointers to 2D arrays, does it have to be int ***table? Or was
I right above?

Finally, note that n[], x[], and b[] should all be unsigned types,
unless you're really sure of yourself (it's easy to get unexpected
behaviour when doing bitwise operations on signed types).


Yeah, I probably should be using unsigned types. I rewrote my orignal
program because in the if statements I had if (... > 0). Then I thought
I might have a problem if the processor thought of some of the numbers
as negative, so I changed it to be if (... != 0). Thanks for your
thoughts. If you, or anyone else, could give any more suggestions I
would be very appreciative. Thanks for your time.

-David C.
Nov 14 '05 #14

P: n/a

On Mon, 26 Apr 2004, David Cleaver wrote:

Old Wolf wrote:

int i;
for (i = 0; i < 30; ++i)
if (table[i][n[i]][x[i]>>5] & b[x[i]&0x1f])
break;
if (i == 30)
do_stuff();
else
{
printf("failed on test %d", i); /* if needed */
do_other_stuff();
}
Thats the opposite of what I want to do, I want n[] and x[] to pass all
of the if tests. I think it should be "if (...) continue; else break;"
right?


Nope. Old Wolf's code checks to make sure all the tests are passed;
if they are, then 'i == 30' will be true, and 'do_stuff' will get
executed. Otherwise (if one of the tests failed), it will print the
error message and then 'do_other_stuff'.
For any given run of the program, each n[k] will be the same, but x[k]
will change as the program runs. So I should probably turn those n's
into constants?
If you define 'n' as an array of const int, your compiler will be
able to determine the best way to generate code for it. Your writing
#define n_0 42
#define n_1 23
#define n_2 11
is definitely *NOT* the right approach.
And since x[k] is changing I can't use a constant
there, or even on b since it depends on x. BTW, my b array is what I'm
using to see if a particular bit is turned on or not. Is there a better
way to do this? Like maybe:
table[][] & (1<<(32 - (x[i]&0x1f) - 1))?
You realize that 32-1 is 31, right? :)

table[ ][ ] & (1<<(31 - (x[i] & 31)))?
instead of:
table[][] & b[x[i]&0x1f]
I don't know which would be faster/better.
It depends. Run a profile if you care so much, but I'd bet you
a large amount that the difference will *not* be significant in the
long run. Micro-optimization is usually Not A Good Idea, *even*
in math programs, and *certainly* not until you have a working
program.
Is this even an appropriate topic for this forum? I don't know where
else to look to ask about writing programs in C AND making them fast.
If this isn't the right spot, could someone please let me know where
would be better?
comp.programming is a more general group that can answer surprisingly
in-depth questions about individual architectures, because it's frequented
by a number of working programmers. (Not that c.l.c isn't; but
processors aren't on topic here.) And then of course there are the
compiler-specific groups like gnu.gcc.help.

If it isn't convenient to have table[] instead of table001, table002 etc.
from the start, then you could set up an array of pointers (you'd only
have to do this once ever).


Ummm, how would I set up an array of pointers? Is that allowed? I
thought all the arrays had to be the same size?


That doesn't make sense to me. Arrays are just arrays. Do you
mean you thought that once you had declared one 30-element array in
your program, all the other arrays had to have 30 elements too? That
would just be masochistic!
And all my tables are of different sizes. Would the array of pointers
look like this:
int *table;
table = (int *) malloc( 30 * sizeof(int));
table[0] = &table001;
table[1] = &table002;
...
Close, but you got the types wrong.

int *table[30];
table[0] = &table001;
table[1] = &table002;
...

would be the natural way to do it IMHO, but of course you could
use dynamic allocation the way you were trying to do:

int **table;
table = malloc(30 * sizeof *table);
if (table == NULL) do_error("out of memory!");
table[0] = &table001;
table[1] = &table002;
...

Finally, note that n[], x[], and b[] should all be unsigned types,
unless you're really sure of yourself (it's easy to get unexpected
behaviour when doing bitwise operations on signed types).


Definitely. Unsigned for bitwise operations, always!
Yeah, I probably should be using unsigned types. I rewrote my orignal
program because in the if statements I had if (... > 0). Then I thought
I might have a problem if the processor thought of some of the numbers
as negative, so I changed it to be if (... != 0). Thanks for your
thoughts. If you, or anyone else, could give any more suggestions I
would be very appreciative. Thanks for your time.


I still haven't understood why you need to have those thirty
tables. Are you legally prevented from telling us what you're
trying to do, or what?

-Arthur
Nov 14 '05 #15

P: n/a


"Arthur J. O'Dwyer" wrote:

On Mon, 26 Apr 2004, David Cleaver wrote:

Old Wolf wrote:

int i;
for (i = 0; i < 30; ++i)
if (table[i][n[i]][x[i]>>5] & b[x[i]&0x1f])
break;
if (i == 30)
do_stuff();
else
{
printf("failed on test %d", i); /* if needed */
do_other_stuff();
}
Thats the opposite of what I want to do, I want n[] and x[] to pass all
of the if tests. I think it should be "if (...) continue; else break;"
right?


Nope. Old Wolf's code checks to make sure all the tests are passed;
if they are, then 'i == 30' will be true, and 'do_stuff' will get
executed. Otherwise (if one of the tests failed), it will print the
error message and then 'do_other_stuff'.


But I thought that "break" would break out of current loop that it is
in, not that it would break out of the if statement. The way I see it:
for (i = 0; i < 30; ++i)
if (table[i][n[i]][x[i]>>5] & b[x[i]&0x1f])
break;
when it gets to "if (...)", if the "..." evaluates to true, then the
"break" instruction is executed which breaks it out of the for loop,
right? So, if at i=0 it were true, none of the other conditions would
be tested. I wanted it to be:
for (i = 0; i < 30; i++)
{
if (table[i][n[i]][x[i]>>5] & b[x[i]&0x1f])
continue; //if true, make sure the next one is true...
else
break; //else, it was false and we need to stop checking...
}//end for
For any given run of the program, each n[k] will be the same, but x[k]
will change as the program runs. So I should probably turn those n's
into constants?
If you define 'n' as an array of const int, your compiler will be
able to determine the best way to generate code for it. Your writing
#define n_0 42
#define n_1 23
#define n_2 11
is definitely *NOT* the right approach.


I'm sorry, I didn't exactly mean that kind of constant. I was thinking
of declaring 30 integers where I would just store each of the n[k]
values. Hoping that just using the int would be faster than an "array
lookup".
And since x[k] is changing I can't use a constant
there, or even on b since it depends on x. BTW, my b array is what I'm
using to see if a particular bit is turned on or not. Is there a better
way to do this? Like maybe:
table[][] & (1<<(32 - (x[i]&0x1f) - 1))?
You realize that 32-1 is 31, right? :)

table[ ][ ] & (1<<(31 - (x[i] & 31)))?


Heh, yes, I do realize 32-1 is 31. I was trying to show what was going
on better, but it looks better your way.
instead of:
table[][] & b[x[i]&0x1f]
I don't know which would be faster/better.
It depends. Run a profile if you care so much, but I'd bet you
a large amount that the difference will *not* be significant in the
long run. Micro-optimization is usually Not A Good Idea, *even*
in math programs, and *certainly* not until you have a working
program.


Ah, well, thanks to the earlier suggestions my program is now up and
running perfectly. Now I'm trying to tweak as much as possible to run
it as fast as possible.
Is this even an appropriate topic for this forum? I don't know where
else to look to ask about writing programs in C AND making them fast.
If this isn't the right spot, could someone please let me know where
would be better?
comp.programming is a more general group that can answer surprisingly
in-depth questions about individual architectures, because it's frequented
by a number of working programmers. (Not that c.l.c isn't; but
processors aren't on topic here.) And then of course there are the
compiler-specific groups like gnu.gcc.help.
If it isn't convenient to have table[] instead of table001, table002 etc.
from the start, then you could set up an array of pointers (you'd only
have to do this once ever).


Ummm, how would I set up an array of pointers? Is that allowed? I
thought all the arrays had to be the same size?


That doesn't make sense to me. Arrays are just arrays. Do you
mean you thought that once you had declared one 30-element array in
your program, all the other arrays had to have 30 elements too? That
would just be masochistic!


No, I thought that if you had a 3D array, like arr[x][y][z], that y and
z had to be the same for all the different values of x. I thought of it
as a 3D array because its an array of pointers to 2D arrays.
And all my tables are of different sizes. Would the array of pointers
look like this:
int *table;
table = (int *) malloc( 30 * sizeof(int));
table[0] = &table001;
table[1] = &table002;
...
Close, but you got the types wrong.

int *table[30];
table[0] = &table001;
table[1] = &table002;
...


Thank you for the clarification.

would be the natural way to do it IMHO, but of course you could
use dynamic allocation the way you were trying to do:

int **table;
table = malloc(30 * sizeof *table);
if (table == NULL) do_error("out of memory!");
table[0] = &table001;
table[1] = &table002;
...
I don't think I want to go down the dynamic route, it won't be too
difficult to do it the other way.
Finally, note that n[], x[], and b[] should all be unsigned types,
unless you're really sure of yourself (it's easy to get unexpected
behaviour when doing bitwise operations on signed types).


Definitely. Unsigned for bitwise operations, always!
Yeah, I probably should be using unsigned types. I rewrote my orignal
program because in the if statements I had if (... > 0). Then I thought
I might have a problem if the processor thought of some of the numbers
as negative, so I changed it to be if (... != 0). Thanks for your
thoughts. If you, or anyone else, could give any more suggestions I
would be very appreciative. Thanks for your time.


I still haven't understood why you need to have those thirty
tables. Are you legally prevented from telling us what you're
trying to do, or what?

-Arthur


Lol, ok, no I'm not prevented from telling you what this is because I am
programming this for myself. Its a math program that attempts to factor
a number N using the difference of squares method. I want to solve N =
x^2 - y^2. I do this by looking at values of (x^2 - N)%p [p a prime]
and then see if that is a possible perfect square mod p. (ie, I'm
looking at S = x^2 - N, to see if S is a possible perfect square mod p.
Then I do this for lots of values of p, each of which reduces the number
of candidates in half. So, looking at 30 different primes reduces the
number of candidates by about 1/(2^30), so this is why I might use more
tables in the future.)

I edited the code a little so it would look better in this newsgroup and
because originally I didn't want to give too much away. Anyway, heres
what my actual (and working thanks to you all) code looks like:
while (1)
{
if ((table003[nmodp[0]][0] & b[xmodp[0]]) &&
(table005[nmodp[1]][0] & b[xmodp[1]]) &&
(table007[nmodp[2]][0] & b[xmodp[2]]) &&
(table011[nmodp[3]][0] & b[xmodp[3]]) &&
...
(table113[nmodp[28]][xmodp[28]>>5] & b[xmodp[28]&0x1f]) &&
(table127[nmodp[29]][xmodp[29]>>5] & b[xmodp[29]&0x1f]))
{
multiply(x, x, x_squared);
subtract(x_squared, test_num, x2_minus_n);

if (nroot(x2_minus_n, 2, y))
{ we_have_a_factor();}//end if
//if true we're done and we break out...
}//end if

incr(x, 1, x);
for (loop_var = 0; loop_var < num_primes; loop_var++)
xmodp[loop_var] = (xmodp[loop_var] + 1)%i_primes[loop_var];
}//end while

I've precomputed those tables. Originally those tables were filled with
int's that held either 0 or 1. Then I rewrote it to pack those 0's and
1's into 32 bit ints (I know its not that portable, but so far its only
running on my system) For a while the if statements looked like:
if ((table003[nmodp[0]][xmodp[0]/32] & b[xmodp[0]%32]) && ...
However, I know from experience that / and % are very slow operations,
so I did a few calculations and found that >>5 and &0x1f would give the
same resutls only lots faster. So, thats why you see a bunch of that in
the above if statements. Also, when p < 32 I don't have to do /32 or
%32 because it just return the same number. (in case you were wondering)

I haven't rewritten it yet to reflect the table[][][] nomenclature, but
I will very soon. Thanks again everyone for all your help.

-David C.
Nov 14 '05 #16

P: n/a
"David Cleaver" <wr*****@morpheus.net> wrote in message
news:40***************@morpheus.net...
For a while the if statements looked like:
if ((table003[nmodp[0]][xmodp[0]/32] & b[xmodp[0]%32]) && ...
However, I know from experience that / and % are very slow operations,
so I did a few calculations and found that >>5 and &0x1f would give the
same resutls only lots faster. So, thats why you see a bunch of that in
the above if statements. Also, when p < 32 I don't have to do /32 or
%32 because it just return the same number. (in case you were wondering)


A decent compiler should do those optimizations (aka strength reduction) for
you, and using /32 and %32 in your source better explains to other readers
what you're trying to do.

S

--
Stephen Sprunk "Stupid people surround themselves with smart
CCIE #3723 people. Smart people surround themselves with
K5SSS smart people who disagree with them." --Aaron Sorkin

Nov 14 '05 #17

P: n/a


"Arthur J. O'Dwyer" wrote:
<snip> Close, but you got the types wrong.

int *table[30];
table[0] = &table001;
table[1] = &table002;
...

would be the natural way to do it IMHO, but of course you could
use dynamic allocation the way you were trying to do:

int **table;
table = malloc(30 * sizeof *table);
if (table == NULL) do_error("out of memory!");
table[0] = &table001;
table[1] = &table002;
... <snip> -Arthur


Ok, I just rewrote it and its not compiling. I went with your first
suggestion, since I don't want to do it dynamically. Here's what I've
written:
int *table[num_primes];
table[0] = &table003; //this is line 70 in the program
table[1] = &table005;
table[2] = &table007;
...
And the compiler gives me these "errors":
blah.c: In function 'blah':
blah.c:70: warning: assignment from incompatible pointer type
blah.c:71: warning: assignment from incompatible pointer type
blah.c:72: warning: assignment from incompatible pointer type
....
blah.c:99: warning: assignment from incompatible pointer type
blah.c:172: subscripted value is neither array nor pointer

here is line 172:
if (table[i][nmodp[i]][xmodp[i]/32] & b[xmodp[i]%32])

What does that mean? What have I done wrong? I'm not seeing it. Can
someone else tell me if I have programmed something wrong or if this
code is just confusing the compiler? Thanks for any help.

-David C.
Nov 14 '05 #18

P: n/a

On Tue, 27 Apr 2004, David Cleaver wrote:

"Arthur J. O'Dwyer" wrote:

int *table[30];
table[0] = &table001;
table[1] = &table002;
...

would be the natural way to do it IMHO
Ok, I just rewrote it and its not compiling. I went with your first
suggestion, since I don't want to do it dynamically. Here's what I've
written:
int *table[num_primes];
table[0] = &table003; //this is line 70 in the program
table[1] = &table005;
table[2] = &table007;
...
And the compiler gives me these "errors":
blah.c: In function 'blah':
blah.c:70: warning: assignment from incompatible pointer type


This tells us that '&table003' is not a pointer to int. I suppose
I wasn't thinking quite clearly when I wrote the code above; obviously,
if 'table001' etc. are arrays[foo] of int, then '&table001' is a
pointer to array[foo] of int, not a pointer to int as we want. So,
drop the '&'s. Done and done.
blah.c:172: subscripted value is neither array nor pointer

here is line 172:
if (table[i][nmodp[i]][xmodp[i]/32] & b[xmodp[i]%32])
Let's see... You're taking 'table', an array of pointers to int,
and subscripting it with '[i]' to yield a single pointer to int.
Then you're subscripting that with '[nmodp[i]]' to yield a single
int. Then you're trying to subscript *that* with '[xmodp[i]/32]'!
That's the error: your code doesn't make any sense. You can't
use an 'int' as if it were a pointer. Why did you change the code
you had? --- this new code seems to do something different!
What does that mean? What have I done wrong? I'm not seeing it. Can
someone else tell me if I have programmed something wrong or if this
code is just confusing the compiler? Thanks for any help.


At this point, all I can tell you is to post a minimal complete,
compilable example that demonstrates your problem, and let the
regulars critique it. You're doling things out in bits and pieces,
and that simply won't fix your errors. There's no need to be so
secretive about things; if you're having problems working with the
type system in C, then you'll need to explain what types you're using
to define your variables. If you're having trouble with control
structures, you'll need to explain the structure of your program.
As you seem to be having trouble with all of this, you'd better
post it all.

(And by "all" I mean a program of maybe 20 to 60 lines with
commentary that tells what the problem is. With the global
variables, #includes and everything. You'll be glad you did.)

HTH,
-Arthur
Nov 14 '05 #19

P: n/a


"Arthur J. O'Dwyer" wrote:
At this point, all I can tell you is to post a minimal complete,
compilable example that demonstrates your problem, and let the
regulars critique it. You're doling things out in bits and pieces,
and that simply won't fix your errors. There's no need to be so
secretive about things; if you're having problems working with the
type system in C, then you'll need to explain what types you're using
to define your variables. If you're having trouble with control
structures, you'll need to explain the structure of your program.
As you seem to be having trouble with all of this, you'd better
post it all.

(And by "all" I mean a program of maybe 20 to 60 lines with
commentary that tells what the problem is. With the global
variables, #includes and everything. You'll be glad you did.)

HTH,
-Arthur


OK, this code is compilable, but it requires the miracl
arbitrary-size-number library to run. If you want me to comment out all
the miracl code, I can do that and then repost. Right now it is
compiling except for the error I mentioned earlier. Actually, I fixed
the last error and now it is just giving all of the warnings. This file
has a #include "arrays.h", if you want to see that I can post it later.
In the code I give an example of what the beginning of arrays.h looks
like.

Should I "inline" the code or "attach" it to this message? If I inline
it, it will definitely not look pretty when it gets through to the other
side. If I attach it, some NG's remove attachments. Please let me know
which way is better.

-David C.
Nov 14 '05 #20

P: n/a
William L. Bahn wrote:

"Chris Dollin" <ke**@hpl.hp.com> wrote in message
The OP is have the *language* make the decision for them - C has a
defined "order of precedence" [1].
The compiler is the one that is making the decision as the compiler is the
one that is compiling the code. I'm not saying that the compiler has any
choice in the decision it makes - and I understand the point you are
making. Please recognize that just saying something like "the compiler is
making the decision" is anthropomorphisizing (sp?) to begin with and the
main point is not who (or what) is making the decision but rather that the
OP is NOT making the decision.


The OP is using the language and has decided to write his code thus-and-so.
The rest is a fixed framework.
Having lots of conditions separated
by && should be no problem at all.

Really? So something like

if( a || b && c || d )

should present no difficulties and compile the way that it was most likely
meant?


I thought my follow-up covered that. I quote:

| Erm, in my haste I did not make it clear that one should still
| write expressions for clarity - there's a difference between knowing
| the C precedence levels, assuming the reader will know them, and
| writing for the IOCC.

As it happens I agree that &&|| mixes can be confusing - I'd look for
better abstractions, rather than bracketing, to fix them, unless the
constituent expressions were tres short.

--
Chris "electric hedgehog" Dollin
C FAQs at: http://www.faqs.org/faqs/by-newsgrou...mp.lang.c.html
C welcome: http://www.angelfire.com/ms3/bchambl...me_to_clc.html
Nov 14 '05 #21

P: n/a

On Tue, 27 Apr 2004, David Cleaver wrote:

"Arthur J. O'Dwyer" wrote:
At this point, all I can tell you is to post a minimal complete,
compilable example that demonstrates your problem, and let the
regulars critique it.
OK, this code is compilable, but it requires the miracl
arbitrary-size-number library to run. If you want me to comment out all
the miracl code, I can do that and then repost.


Well, you're going to have to repost anyway, since I don't see any
code attached to your post this time. Since I occasionally see
attachments on my newsfeed, I'm assuming the stripping-of-attachments
is happening somewhere between you and me.
(This is why we --- and everyone else --- tell people not to post
attachments to text-only Usenet groups.)
Should I "inline" the code or "attach" it to this message? If I inline
it, it will definitely not look pretty when it gets through to the other
side. If I attach it, some NG's remove attachments. Please let me know
which way is better.


Posting the code in the message body is better. Your comment about
its "not looking pretty" doesn't make sense --- just think of your
news client's text window (or text-entry area) as a text editor's
window (or text-entry area). Anything that doesn't fit in a 75-character
line needs to be snipped and/or reformatted.
You should never use "hard tabs" on Usenet. (IMHO, you should never
use "hard tabs" in source code, period, especially since the advent of
automatic indenting tools, but *definitely* not on Usenet.)
And of course in c.l.c you shouldn't be using // comments, either
because in C90 they're invalid or because in C99 they're just a royal
PITA to deal with. (Consider the following line of code:

int myident = foo(baz); // Here, we are calling 'foo' to get the
value of sqrt|baz| as an int.

Oh dear, line-wrapping has broken our program!)

Other than these caveats --- which can be handled simply enough by
a mechanical approach --- there's no reason for your code to look ugly.
Unless, of course, it looked ugly to begin with. And then that's your
problem. :)

HTH,
-Arthur

[P.S.: Has anyone ever written a "Usenet code formatter" for C code
that would wrap long lines in the right places, replace // comments
with /* comments */, and detab intelligently? It might find an
audience... ;-) ]
Nov 14 '05 #22

P: n/a


"Arthur J. O'Dwyer" wrote:
Posting the code in the message body is better. Your comment about
its "not looking pretty" doesn't make sense --- just think of your
news client's text window (or text-entry area) as a text editor's
window (or text-entry area). Anything that doesn't fit in a 75-character
line needs to be snipped and/or reformatted.
Ah, 75 characters, well, here it is in 75 character width glory
(unfortunately, its a bit longer than the 20-60 lines you said earlier, I
wasn't sure what to cut out so I left alot in. This gets called from
another program, so thats why you aren't seeing a main()).
Except for the warnings I've mentioned, it compiles just fine with "gcc -c"

#include <stdio.h>
#include <miracl.h>
#include "arrays.h"

/*================================================= ======================*/

void quadSieve(big test_num, big divisor)
{

/* num_primes = 30, its defined in "arrays.h" */
int i_primes[num_primes] = {3,5,7,11,13,17,19,23,29,31,37,41,
43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,10 9,113,127};
int b[32] = {0x80000000, 0x40000000, 0x20000000, 0x10000000,
0x8000000, 0x4000000, 0x2000000, 0x1000000,0x800000, 0x400000,
0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000, 0x4000,
0x2000, 0x1000,
0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
int xmodp[num_primes];
int nmodp[num_primes]; /* this holds test_num%p, p a prime */
int **table[num_primes];
int loop_var = 0;
int i = 0;
big x;
big y;
big x_squared;
big x_minus_y;
big x2_minus_n;

/* Now allocate our big vars... */
x = mirvar(0);
y = mirvar(0);
x_squared = mirvar(0);
x_minus_y = mirvar(0);
x2_minus_n = mirvar(0);
/*
**now, create pointers to our 2D arrays...**
"Old Wolf" on comp.lang.c suggested that I create an array of pointers
to my 2-dimensional tables so that I could just make a for loop to
test everything instead of writing it all out in one very large if
statement, so here I am attempting to create an array of pointers to
all of my 2D arrays. Just to give you an idea of the size of each of
these 2D arrays, int table003[3][1], int table005[5][1], ...,
int table037[37][2], and table_k is of size int table_k[k][(k/32)+1],
these are all defined in "arrays.h" And if you want to actually see
one of the defined tables, then here is the beginning of arrays.h:
#ifndef arrays_h_
#define arrays_h_

#define num_primes 30
int table003[3][1] = {{ 0xe0000000},
{ 0x60000000},
{ 0x80000000}};
Following is the part of the code the compiler is having problems with.
The compiler has no problems with the rest of the code.
I guess my only question is how do I create an array pointing to all
of my already declared 2D arrays.
*/
table[0] = &table003;
table[1] = &table005;
table[2] = &table007;
table[3] = &table011;
table[4] = &table013;
table[5] = &table017;
table[6] = &table019;
table[7] = &table023;
table[8] = &table029;
table[9] = &table031;
table[10] = &table037;
table[11] = &table041;
table[12] = &table043;
table[13] = &table047;
table[14] = &table053;
table[15] = &table059;
table[16] = &table061;
table[17] = &table067;
table[18] = &table071;
table[19] = &table073;
table[20] = &table079;
table[21] = &table083;
table[22] = &table089;
table[23] = &table097;
table[24] = &table101;
table[25] = &table103;
table[26] = &table107;
table[27] = &table109;
table[28] = &table113;
table[29] = &table127;

printf("Attempting to factor: ");
outnum(test_num, stdout);
printf("\n");

/*
if test_num is a perfect square, this will catch it...
*/
if (nroot(test_num, 2, x))
{
copy(x, divisor);
return;
}//end if
/*
if we get here, then test_num was not a perfect square and
the floor of the square root of test_num is in x, since we need
the ceil, we will now increment x by one...
*/
incr(x, 1, x);
printf("Initial x: ");
outnum(x, stdout);
printf("\n");

/*
now fill in our two arrays...
*/
for (loop_var = 0; loop_var < num_primes; loop_var++)
{
xmodp[loop_var] = remain(x, i_primes[loop_var]);
nmodp[loop_var] = remain(test_num, i_primes[loop_var]);
}/* end for */

while (1)
{
for (i = 0; i < num_primes; i++)
{
if (table[i][nmodp[i]][xmodp[i]/32] & b[xmodp[i]%32])
continue;
else
break;
}/* end for */

/*if it passed all of the above tests then it should be = num_primes = 30*/
if (i == num_primes)
{
multiply(x, x, x_squared);
subtract(x_squared, test_num, x2_minus_n);

/*if we get a perfect square, then we are done and we get out of dodge...*/
if (nroot(x2_minus_n, 2, y))
{
subtract(x, y, x_minus_y);
copy(x_minus_y, divisor);

mirkill(x);
mirkill(y);
mirkill(x_squared);
mirkill(x_minus_y);
mirkill(x2_minus_n);

return;
}/*end if*/
}/*end if*/

incr(x, 1, x);
for (loop_var = 0; loop_var < num_primes; loop_var++)
xmodp[loop_var] = (xmodp[loop_var] + 1)%i_primes[loop_var];
}/*end while*/
}/*method quadSieve*/

You should never use "hard tabs" on Usenet. (IMHO, you should never
use "hard tabs" in source code, period, especially since the advent of
automatic indenting tools, but *definitely* not on Usenet.)
OK, I've gotten rid of the hard tabs, and just used two-spaces instead. I
don't have any "automatic indenting tools". I just use notepad to do my
programming.
And of course in c.l.c you shouldn't be using // comments, either
because in C90 they're invalid or because in C99 they're just a royal
PITA to deal with. (Consider the following line of code:

int myident = foo(baz); // Here, we are calling 'foo' to get the
value of sqrt|baz| as an int.

Oh dear, line-wrapping has broken our program!)
OK, I've gotten rid of all of the // type comments and replaced them all
with /* ... */

Other than these caveats --- which can be handled simply enough by
a mechanical approach --- there's no reason for your code to look ugly.
Unless, of course, it looked ugly to begin with. And then that's your
problem. :)

HTH,
-Arthur


I don't think it was all that ugly, its just that sometimes line-wrapping
makes it look bad. I think it actually looked better back when I was using
my // style comments, but since I changed that for this post you won't see
it. Anyway, my current problem is creating an array that points to all of
my already declared 2D arrays. The reason I don't want to make a 3D array
is because that would waste alot of space. I want to try and keep my
tables as small as possible.

Well, please let me know if it is possible in C to create an array that
points to a bunch of other 2-dimensional arrays that are all of differing
sizes. Thanks for your time.

-David C.
Nov 14 '05 #23

P: n/a
David Cleaver <wr*****@morpheus.net> wrote:
"Arthur J. O'Dwyer" wrote:

Ok, I just rewrote it and its not compiling. I went with your first
suggestion, since I don't want to do it dynamically. Here's what I've
written:
int *table[num_primes];
table[0] = &table003; //this is line 70 in the program
table[1] = &table005;
table[2] = &table007;
...
And the compiler gives me these "errors":
blah.c: In function 'blah':
blah.c:70: warning: assignment from incompatible pointer type

blah.c:172: subscripted value is neither array nor pointer
here is line 172:
if (table[i][nmodp[i]][xmodp[i]/32] & b[xmodp[i]%32])

What does that mean? What have I done wrong? I'm not seeing it.


You haven't posted the definitions of table003 etc. but I'm presuming
you have something like:
int table003[10][20] = ...
int table005[30][40] = ...
int table007[25][35] = ...

table[0] is a pointer to int. table003 is an array[10][20] of int.
So you can't point one to the other. The best you can do with your
table[0] is point it to the first int in table003, but this will
not be good enough because you cannot tell from that pointer how to
get to the second row of the table, for example.

Your error message on line 172 is saying that "table[i]"[foo]" cannot
be followed by [bar], which makes sense because table[i] is a pointer
to int, so table[i][foo] is an actual int.

Since the tables have varying widths, you will have to remember the
width along with a pointer to the first element. Try this:
int *table[] = { table003, table005, ... };
const int table_width[] = { sizeof *table003, sizeof *table005, ... };
and then:
if (table[i][ nmodp[i] * table_width[i] + xmodp[i]/32 ] & b[xmodp[i]%32])

This doesn't represent a slow-down, because when you went
table[i][foo][bar], the compiler silently interprets it as
table[i][foo * sizeof *table[i] + bar] anyway . There is a small
amount of slowdown in retrieving the table width instead of having
it in the source, but I would expect that if you did some profiling
on the loop version once you're finished, there wouldn't be a noticeable
difference.

Re. other posts on the thread: just because you get something compiling
doesn't mean it's actually going to work, and you were correct that
I wrote "if (cond) break;" but what you actually wanted was
"if (!(cond)) break;", which is exactly equivalent to
"if (cond) continue; else break;", as you pointed out.
Nov 14 '05 #24

P: n/a
On Tue, 27 Apr 2004 02:26:23 -0500, David Cleaver wrote:


"Arthur J. O'Dwyer" wrote: [snip about minimal compiling program]
(And by "all" I mean a program of maybe 20 to 60 lines with
commentary that tells what the problem is. With the global
variables, #includes and everything. You'll be glad you did.)

HTH,
-Arthur


OK, this code is compilable, but it requires the miracl
arbitrary-size-number library to run.


What code? Where? I see no code here.
If you want me to comment out all
the miracl code, I can do that and then repost.
I don't see any big problem about libraries: They rarely impact the
standards-conformance of the code that calls into them. Providing
prototypes for subroutines might be a plus.

Should I "inline" the code or "attach" it to this message? If I inline
it, it will definitely not look pretty when it gets through to the other
side. If I attach it, some NG's remove attachments. Please let me know
which way is better.
Inlining, definitely. Otherwise, there are more than a few people here who
don't get the code at all.

-David C.


--
yvoregnevna gjragl-guerr gjb-gubhfnaq guerr ng lnubb qbg pbz
To email me, rot13 and convert spelled-out numbers to numeric form.
"Makes hackers smile" makes hackers smile.

Nov 14 '05 #25

P: n/a


Old Wolf wrote:

David Cleaver <wr*****@morpheus.net> wrote:
"Arthur J. O'Dwyer" wrote:

Ok, I just rewrote it and its not compiling. I went with your first
suggestion, since I don't want to do it dynamically. Here's what I've
written:
int *table[num_primes];
table[0] = &table003; //this is line 70 in the program
table[1] = &table005;
table[2] = &table007;
...
And the compiler gives me these "errors":
blah.c: In function 'blah':
blah.c:70: warning: assignment from incompatible pointer type

blah.c:172: subscripted value is neither array nor pointer
here is line 172:
if (table[i][nmodp[i]][xmodp[i]/32] & b[xmodp[i]%32])

What does that mean? What have I done wrong? I'm not seeing it.
You haven't posted the definitions of table003 etc. but I'm presuming
you have something like:
int table003[10][20] = ...
int table005[30][40] = ...
int table007[25][35] = ...


Yes, this is how I have declared those arrays.

table[0] is a pointer to int. table003 is an array[10][20] of int.
So you can't point one to the other. The best you can do with your
table[0] is point it to the first int in table003, but this will
not be good enough because you cannot tell from that pointer how to
get to the second row of the table, for example.

Your error message on line 172 is saying that "table[i]"[foo]" cannot
be followed by [bar], which makes sense because table[i] is a pointer
to int, so table[i][foo] is an actual int.

Since the tables have varying widths, you will have to remember the
width along with a pointer to the first element. Try this:
int *table[] = { table003, table005, ... };
const int table_width[] = { sizeof *table003, sizeof *table005, ... };
and then:
if (table[i][ nmodp[i] * table_width[i] + xmodp[i]/32 ] & b[xmodp[i]%32])
OK, I've done this, but the compiler is still giving warnings about
initializations from incompatible pointer types. It looks like:
blah.c: In function 'blah':
blah.c:44: warning: initialization from incompatible pointer type
....

Line 44 is where I have:
int *table[] = { table003, table005,...};
I even tried:
int *table[] = { &table003, &table005,...};
But neither of the above made it past the compiler without the compiler
giving warnings. The code actually does compile, but I'm not sure I'd
trust it to run correctly. Any thoughts on how to get around this? Or is
this valid C and I'm just stuck with a sub-par compiler?

This doesn't represent a slow-down, because when you went
table[i][foo][bar], the compiler silently interprets it as
table[i][foo * sizeof *table[i] + bar] anyway . There is a small
amount of slowdown in retrieving the table width instead of having
it in the source, but I would expect that if you did some profiling
on the loop version once you're finished, there wouldn't be a noticeable
difference.

Re. other posts on the thread: just because you get something compiling
doesn't mean it's actually going to work, and you were correct that
I wrote "if (cond) break;" but what you actually wanted was
"if (!(cond)) break;", which is exactly equivalent to
"if (cond) continue; else break;", as you pointed out.


Thanks again for your help so far.

-David C.
Nov 14 '05 #26

P: n/a
David Cleaver <wr*****@morpheus.net> wrote:
Old Wolf wrote:
Since the tables have varying widths, you will have to remember the
width along with a pointer to the first element. Try this:
int *table[] = { table003, table005, ... };
const int table_width[] = { sizeof *table003, sizeof *table005, ... };
and then:
if (table[i][ nmodp[i] * table_width[i] + xmodp[i]/32 ] & b[xmodp[i]%32])


OK, I've done this, but the compiler is still giving warnings about
initializations from incompatible pointer types. It looks like:
blah.c: In function 'blah':
blah.c:44: warning: initialization from incompatible pointer type


My mistake - the address of the first int in the table is &table003[0][0]
etc., which can be written more compactly as *table003, so you can go:
int *table[] = { *table003, *table005, *table007 }; etc.
Nov 14 '05 #27

P: n/a


Old Wolf wrote:

David Cleaver <wr*****@morpheus.net> wrote:
Old Wolf wrote:
Since the tables have varying widths, you will have to remember the
width along with a pointer to the first element. Try this:
int *table[] = { table003, table005, ... };
const int table_width[] = { sizeof *table003, sizeof *table005, ... };
and then:
if (table[i][ nmodp[i] * table_width[i] + xmodp[i]/32 ] & b[xmodp[i]%32])


OK, I've done this, but the compiler is still giving warnings about
initializations from incompatible pointer types. It looks like:
blah.c: In function 'blah':
blah.c:44: warning: initialization from incompatible pointer type


My mistake - the address of the first int in the table is &table003[0][0]
etc., which can be written more compactly as *table003, so you can go:
int *table[] = { *table003, *table005, *table007 }; etc.


Exellent! It works perfectly now! Thank you very much! Actually, I also
found out one thing, when working with the table_width, the "sizeof
*table003" returned the size of the variable in bytes, and not in ints.
So, I had to go back through and divide it by (sizeof(int)) to get the
array access at:
if (table[i][ nmodp[i] * table_width[i] + xmodp[i]/32 ] & b[xmodp[i]%32])
to work properly.

I do have one more question if you don't mind. I would like to write the
above array declarations more succinctly. Instead of writing:
const int table_width[] = { sizeof *table003, sizeof *table005,...
for 30 (or more) different tables, I would like to write:

int table_width[num_primes];
for (i = 0; i < num_primes; i++)
table_width[num_primes] = (sizeof *table[i])/(sizeof(int));

However, when I run this code all that is in table_width is a bunch of
ones. For the first 10 tables thats ok, but the rest are larger than "1".
There are some 2's, 3's, and a couple of 4's also. Can you tell me if
there is a way I can do this, since apparently the code I tried to write
isn't quite cutting it. Thanks again for all your help so far.

-David C.
Nov 14 '05 #28

P: n/a

On Wed, 28 Apr 2004, David Cleaver wrote:

Old Wolf wrote:
David Cleaver <wr*****@morpheus.net> wrote:
Old Wolf wrote:
> Since the tables have varying widths, you will have to remember the
> width along with a pointer to the first element. Try this:
> int *table[] = { table003, table005, ... };
> const int table_width[] = {sizeof *table003, sizeof *table005, ...
My mistake - the address of the first int in the table is &table003[0][0]
etc., which can be written more compactly as *table003, so you can go:
int *table[] = { *table003, *table005, *table007 }; etc.


Exellent! It works perfectly now! Thank you very much! Actually, I also
found out one thing, when working with the table_width, the "sizeof
*table003" returned the size of the variable in bytes, and not in ints.


Correct --- the 'sizeof' operator *always* deals in bytes.
So, I had to go back through and divide it by (sizeof(int)) to get the
array access at:
if (table[i][ nmodp[i] * table_width[i] + xmodp[i]/32 ] & b[xmodp[i]%32])
to work properly.
One common C idiom you should know is

#define NELEM(arr) (sizeof arr / sizeof *arr)

This macro, given an array object as the 'arr' parameter, will tell
you the number of elements in that array. (It will NOT work on
pointers, for obvious reasons!)
I do have one more question if you don't mind. I would like to write the
above array declarations more succinctly. Instead of writing:
const int table_width[] = { sizeof *table003, sizeof *table005,...
for 30 (or more) different tables, I would like to write:

int table_width[num_primes];
for (i = 0; i < num_primes; i++)
table_width[num_primes] = (sizeof *table[i])/(sizeof(int));

However, when I run this code all that is in table_width is a bunch of
ones.


Well, naturally. Let's evaluate that code above:

for (i = 0; i < num_primes; i++)
table_width[num_primes] =

What have I told you about hard TABs in posted code?...
Secondly, we see that you're assigning something to a non-existent
object 'num_primes' times. Redundant *and* wrong --- that's never
a good sign.

(sizeof *table[i])

This evaluates to the size of *table[i] in bytes. Since *table[i]
is an 'int', this is the same as 'sizeof (int)'.

/(sizeof(int));

This is *also* 'sizeof(int)', so of course the result is 1.
Assign to the non-existent 'table_width[num_primes]', rinse,
and repeat.

The only correct solution is the solution Old Wolf already
gave you:

int table_width[] = { NELEM(table003), NELEM(table005), ... };

Of course there are preprocessor tricks to save you a lot of
typing, but why bother? If you find yourself unable to hammer
in the screw with this tool, just try a different one. For
example:

int table003[] = { ...., -1 };
int table005[] = { ........, -1 };
int table007[] = { ......, -1 };

int find_size(int *tab)
{
int i;
for (i=0; tab[i] != -1; ++i)
continue;
return i;
}

Or perhaps just try an algorithm that doesn't require a load of
variously-sized arrays to work. What were you trying to do, again
--- was it primality testing? I'm sure there exist better algorithms
than this one. Bunches of tables always make me suspicious.

-Arthur
Nov 14 '05 #29

P: n/a
David Cleaver wrote:
David Cleaver wrote:

if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
... &&
table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
{
.... snip ...
Thank you very much. I never thought about there being a precedence
issue. I've fixed my code to better reflect what I was doing. [And
I was wanting (x & y), not x & (y != 0), I've changed it all to be
of the form (x & y) && ...]

May I ask, without making those tables 3-dimensional, how could I
make that code segment look better? Someone earlier in this thread
mentioned putting it into a for loop, but I can't see how that'd be
possible with 30 different tables.


There is no such thing as a 2d or 3d array in C; they are all one
dimensional. The 2d/3d effects can be simulated by changing what
the array component consists of.

So let us assume that you have your existing table001, table002,
etc. set up and functional. You can now create an array of
pointers to these tables, say:

int *tables[] = {&table000, &table001, &table002, &table003,
&table004, &table005, ....
&table028, &table029};

#define TABLEMAX = (sizeof(tables) / sizeof(table[0]))

Now you can evaluate the equivalent of your expression above, with
corrected precedence, with a routine such as:

int querytbls(int *tables)
{
int i;
for (i = 1; i < TABLEMAX; i++) {
if (0 == *(tables[i])[n[i][x[i] >> 5] & b[x[i] & 0x1f])
return 0;
}
return 1;
} /* untested */

Now all you have to do to modify it is create the appropriate
tables and add them to the declaration of tables above. The point
is that the machine and the compiler are much better at this sort
of bum work than you or I are.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #30

P: n/a
On Thu, 29 Apr 2004, CBFalconer <cb********@yahoo.com> wrote:
David Cleaver wrote:
David Cleaver wrote:
>
> if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
> table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
> table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
> ... &&
> table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
> {
... snip ...


int *tables[] = {&table000, &table001, &table002, &table003,
&table004, &table005, ....
&table028, &table029};

#define TABLEMAX = (sizeof(tables) / sizeof(table[0]))

Now you can evaluate the equivalent of your expression above, with
corrected precedence, with a routine such as:

int querytbls(int *tables)
{
int i;
for (i = 1; i < TABLEMAX; i++) {
if (0 == *(tables[i])[n[i][x[i] >> 5] & b[x[i] & 0x1f])
in the above seems to me you have forget ']'
if it is v
if (0 == *(tables[i])[n[i]][x[i] >> 5] & b[x[i] & 0x1f])
you know that it is evaluated like
if( (0==*(tables[i])[n[i]][x[i]>>5]) & b[x[i] & 0x1f] )

I would write
"if( (tables[i][n[i]][x[i]>>5] & b[x[i] & 0x1f] )==0 )"

CBFalconer it\she\they-- Ros 0, 2 return 0;
}
return 1;
} /* untested */

Nov 14 '05 #31

P: n/a
On Thu, 29 Apr 2004 16:45:39 GMT, CBFalconer <cb********@yahoo.com>
wrote:
David Cleaver wrote:
David Cleaver wrote:
>
> if (table001[n[0]][x[0]>>5]&b[x[0]&0x1f] != 0 &&
> table002[n[1]][x[1]>>5]&b[x[1]&0x1f] != 0 &&
> table003[n[2]][x[2]>>5]&b[x[2]&0x1f] != 0 &&
> ... &&
> table030[n[29]][x[29]>>5]&b[x[29]&0x1f] != 0)
> {
... snip ...

Thank you very much. I never thought about there being a precedence
issue. I've fixed my code to better reflect what I was doing. [And
I was wanting (x & y), not x & (y != 0), I've changed it all to be
of the form (x & y) && ...]

May I ask, without making those tables 3-dimensional, how could I
make that code segment look better? Someone earlier in this thread
mentioned putting it into a for loop, but I can't see how that'd be
possible with 30 different tables.


There is no such thing as a 2d or 3d array in C; they are all one
dimensional. The 2d/3d effects can be simulated by changing what
the array component consists of.

So let us assume that you have your existing table001, table002,
etc. set up and functional. You can now create an array of
pointers to these tables, say:

int *tables[] = {&table000, &table001, &table002, &table003,
&table004, &table005, ....
&table028, &table029};

#define TABLEMAX = (sizeof(tables) / sizeof(table[0]))

Now you can evaluate the equivalent of your expression above, with
corrected precedence, with a routine such as:

int querytbls(int *tables)

here int **tables
1 error
{
int i;
for (i = 1; i < TABLEMAX; i++) {
if (0 == *(tables[i])[n[i][x[i] >> 5] & b[x[i] & 0x1f]) here
if ( ( *(tables[i])[n[i]][x[i] >> 5] & b[x[i] & 0x1f] ) == 0)
1+1 errors
=3
return 0;
}
return 1;
} /* untested */


Nov 14 '05 #32

P: n/a
On Mon, 26 Apr 2004 14:04:33 -0600, "William L. Bahn"
<wi*****@toomuchspam.net> wrote:

Really? So something like

if( a || b && c || d ) =
if( a || (b && c) || d)
should present no difficulties and compile the way that it was most likely
meant?


Nov 14 '05 #33

P: n/a


"Arthur J. O'Dwyer" wrote:

On Wed, 28 Apr 2004, David Cleaver wrote:

Old Wolf wrote:
David Cleaver wrote:
> Old Wolf wrote:
> > Since the tables have varying widths, you will have to remember the
> > width along with a pointer to the first element. Try this:
> > int *table[] = { table003, table005, ... };
> > const int table_width[] = {sizeof *table003, sizeof *table005, ...

My mistake - the address of the first int in the table is &table003[0][0]
etc., which can be written more compactly as *table003, so you can go:
int *table[] = { *table003, *table005, *table007 }; etc.


Exellent! It works perfectly now! Thank you very much! Actually, I also
found out one thing, when working with the table_width, the "sizeof
*table003" returned the size of the variable in bytes, and not in ints.


Correct --- the 'sizeof' operator *always* deals in bytes.
So, I had to go back through and divide it by (sizeof(int)) to get the
array access at:
if (table[i][ nmodp[i] * table_width[i] + xmodp[i]/32 ] & b[xmodp[i]%32])
to work properly.


One common C idiom you should know is

#define NELEM(arr) (sizeof arr / sizeof *arr)

This macro, given an array object as the 'arr' parameter, will tell
you the number of elements in that array. (It will NOT work on
pointers, for obvious reasons!)


Why won't it work on what the pointers are pointing to?

int *table[] = { table003, table005, ... };
int table_width[] = {sizeof *table003, sizeof *table005, ... };

table[i] holds a pointer to table003, table005, ... right?
So, instead of doing the above, why can't I use:

int *table[] = { table003, table005, ... };
for (i = 0; i < num_primes; i++)
table_width[i] = sizeof **table[i];

Is C incapable of doing this? Is the information lost when we create our
array of pointers? I'm just curious why this won't work. Thanks for any
insights you (or anyone else) can provide.

-David C.
Nov 14 '05 #34

P: n/a
In article <news:40***************@morpheus.net>
David Cleaver <wr*****@morpheus.net> writes:
Why won't [the sizeof sequence, "sizeof array / sizeof array[0]" for
instance] work on what the pointers are pointing to?
Because pointers lose information. The extra information attached
to an array object (besides its name, static-ness, etc.) is a *pair*
of things:

number-of-elements = N, element-type = T

(where N is an integer constant in C89, or the special value "unknown";
C99 adds a new wrinkle with Variable Length Arrays). The information
attached to a pointer object is just one item:

pointer-target-type = T

and The Rule that transforms an array object into a pointer value
discards the number-of-elements portion.

The sizeof operator is one of the few operators that does *not*
transform an array object into a pointer value. By suppressing
this transformation, it avoids losing the size information.
... Is the information lost when we create our array of pointers?


Yes.

There is another approach you can use -- instead of carrying the
sizes around in an auxiliary array, you can carry the locations
around in an auxiliary array.

To recap: you have (at the moment) a collection of one-dimensional
arrays whose elements are in turn one-dimensional arrays (of int,
I think). That is, you have an object like "table003" whose type
is "array N1 of (array N2 of int)", then one like table005, and
one like table013, and so on. Unfortunately, the element-types --
"array N2 of int" for table003 for instance -- change, because the
constant (N2) is different for table003 than for table041, whose
constant is different from that for table097, and so on.

The trick, as always, is to draw a picture, something like the
one that can be found at <http://web.torek.net/torek/c/pa.html>.
In this case, however, the picture is much more complicated. We
have:

table003:
-----
| . |
-----
| . |
-----
| . |
-----
...
table041:
-------------
| . | . | . |
-------------
| . | . | . |
-------------
| . | . | . |
-------------

Because pointers must encode the size of the element to which
they point, a pointer to a "row" of table041 has to point to
a three-long-row (in the example above), while a pointer to a
"row" of table003 has to point to a one-long row (in the example
above). Thus, you cannot use a single pointer type to point to
both "rows of table003" and "rows of table041".

The trick discussed earlier is to point not to *rows* of each table,
but to the *very first int* in each table -- the box at (0,0).
Since C requires that array memory be "locally flat", and C compilers
that check for exceeding array subscript bounds are so rare that
few have ever even heard of one, we can then "cheat". Adding 1 to
a pointer pointing to table041[0][0] gets you to table041[0][1];
adding 1 again gets you to table041[0][2]; and adding 1 more is
*technically* undefined -- there is no table041[0][3] -- but on
all "real world" implementations it just wraps around to get to to
table041[1][0]. In table003, the wrap-around occurs right away,
because there is a table003[0][0] but no table003[0][1].

Instead of using this undefined behavior to achieve the desired
effect, though, you can throw more memory at the problem. (This
may actually slow it down.) Take the above drawing, with table003
and table041 as they are, and add some auxiliary tables:

aux_ptrs_for_003: table003:
------------- -----
| * | * | *-|-----> | . |
--|---|------ -----
| +-----------> | . |
| -----
+---------------> | . |
-----
...
aux_ptrs_for_041: table041:
------------- -------------
| * | * | *-|-----> | . | . | . |
--|---|------ -------------
| +-----------> | . | . | . |
| -------------
+---------------> | . | . | . |
-------------

Now each "aux_ptrs_for_nnn" array has type "array N of pointer to
int". (In the example above, N is always 3, but in practice it
will -- presumably -- vary. This will not matter because we are
about to eliminate the constant N, through that very same thing
that causes heartache with "sizeof".) Each "aux" array has its
various elements pointing to the [0][0], [1][0], and [2][0] element
of the corresponding "table". Just for illustration I will make
table003 only have two rows here:

int table003[2][1] = { ... };
int table041[3][3] = { ... };

int *aux_003[2] = { &table003[0][0], &table003[1][0] };
int *aux_041[3] = { &table041[0][0], &table041[1][0], &table041[2][0] };

Now we just need one last table, the "table of pointers that
points to the first of each aux pointer". For illustration
I will add aux_005 and aux_007 (not shown above):

#define N1 4 /* table[0] through table[3] */
int **table[N1] = { &aux_003[0], &aux_005[0], &aux_007[0], &aux_041[0] };

The picture here looks like this:

table: aux_007:
----------------- -------------
| * | * | * | * | +-> | * | * | * | (pointer arrows not shown)
--|---|---|---|-- | -------------
. | | | |
. | +---|----------+
. . |
v . | aux_042:
(aux_003). | -------------
v +--> | * | * | * |
(aux_005) -------------

Note that all of the "aux" arrays may be scattered around anywhere
in memory; all we demand is that there be a set of pointers to them,
all in a neat row, in the thing called "table". Each pointer --
each element of the table named "table" -- has type "pointer to
(pointer to int)", so that it points to the first of some unspecified
number of pointers. Each of those pointers has type "pointer to
int", so that it points to the first of some unspecified number
of "int"s.

If you look in table[0], you get the arrow pointing to aux_003[0].
If you follow that arrow -- as is the case for normal uses of the
value, including further subscripting -- you get the first element
of the array "aux_003", which is another pointer -- another arrow.
You can subscript by however many elements there really are in the
aux_003 array, to get the j'th pointer: table[0][j] is the j'th
pointer in the aux_003 array. Follow *that* arrow and you point
to table003[j][0], because we made aux_003[j] point to table003[j][0]
when we created the aux_003 array.

Thus, table[i][j][k] is the i'th "aux" array, then its "j'th" element
(which points to the j'th row of a tableNNN), then that row's k'th
element.

Note that the table named "table" itself, and table[i], and
table[i][j], can all be dynamically allocated (by replacing the
array "table", of size N1, with a pointer to the same element type
that the table array had), if you prefer:

int ***table;

table = malloc(N1 * sizeof *table);
if (table == NULL) ...
/* now table[i], 0 <= i < N1, is valid */

table[i] = malloc(N2 * sizeof *table[i]);
if (table[i] == NULL) ...
/* now table[i][j], 0 <= j <= N2; is valid */

table[i][j] = malloc(N3 * siezof *table[i][j]);
if (table[i][j] == NULL) ...
/* now table[i][j][k], 0 <= k < N3, is valid */

As before, there is no reason that N2 has to be the same for every
value of i, nor that N3 has to be the same for every pair (i,j).
If you draw a picture of this situation, it will look almost the
same as the one where "table" has type "int **[4]", except that
the four "int **" elements are now floating off in space somewhere
and "table" is just a pointer pointing to the first one, and the
"aux" name are gone -- they too are just floating off in space,
allocated by malloc:

table:
-----
| *-|--+
----- |
|
+-------------+
|
| ----------------- -------------
+->| * | * | * | * | +-> | * | * | * | (pointer arrows not shown)
--|---|---|---|-- | -------------
. | | | |
. | +---|----------+
. . |
v . |
. | -------------
v +--> | * | * | * |
-------------
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (4039.22'N, 11150.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #35

P: n/a
David Cleaver <wr*****@morpheus.net> wrote:
Old Wolf wrote:
David Cleaver <wr*****@morpheus.net> wrote:
Old Wolf wrote:
> Since the tables have varying widths, you will have to remember the
> width along with a pointer to the first element. Try this:

[we ended up with the following code: ]
int *table[] = { *table003, *table005, *table007 }; etc.
const int table_width[] = { sizeof *table003, sizeof *table005, ... };
and refer to each int as:
table[i][ nmodp[i] * table_width[i] + xmodp[i]/32 ]
Exellent! It works perfectly now! Thank you very much! Actually, I also
found out one thing, when working with the table_width, the "sizeof
*table003" returned the size of the variable in bytes, and not in ints.
So, I had to go back through and divide it by (sizeof(int)) to get the
array access at:
if (table[i][ nmodp[i] * table_width[i] + xmodp[i]/32 ] & b[xmodp[i]%32])
to work properly.
Right.
I do have one more question if you don't mind. I would like to write the
above array declarations more succinctly.
You could go:
const int table_width[] = { dimof(*table003), dimof(*table005), ... };
with
#define dimof(x) (sizeof(x) / sizeof((x)[0]))
(or call this macro something that makes sense to you)

which gives you the number of items in each array (divide the size
in bytes, by the size of each item). In this case, the sizeof **table003
is sizeof(int). This is probably best, as all the maths is done at
compile time.
Instead of writing:
const int table_width[] = { sizeof *table003, sizeof *table005,...
for 30 (or more) different tables, I would like to write:

int table_width[num_primes];
for (i = 0; i < num_primes; i++)
table_width[num_primes] = (sizeof *table[i])/(sizeof(int));


table[i] is a pointer to int. (NOT a pointer to array)
*table[i] is an int.
sizeof(*table[i]) is therefore the same as sizeof(int).

You can't have an array of pointers to arrays of different widths,
which is why we settled for the solution of having an array of
pointers to int.

Just adding the "/sizeof(int)" into the table[i][blah] is
also an option.
Nov 14 '05 #36

This discussion thread is closed

Replies have been disabled for this discussion.