I want to quit of both "for" loop whenever I find x[i][j]=1;
Do you know how to do it?
Right now, I am using the following code but I believe there should be
a much more efficient way for this task.
flag=0;
for (i=0;i<H;i++)
{
for (j=0;j<H;j++)
if (x[i][j]==1)
{
flag=1;
break;
}
if( flag)
break
}
Thanks
I doubt that efficient is really the issue here. I think elegance is
more what you are thinking of :-)
As C doesn't have a labelled break (disclaimer: I haven't checked
C99), you have to do something similar to what you have.
See http://c-faq.com/misc/multibreak.html which makes a few other
suggestions.
I'd probably do a small variation on what you have here :-
found = 0;
for (i=0;i<H && !found;i++) {
for (j=0;j<H && !found;j++) {
if (x[i][j]==1) {
found=1;
}
}
}
Which may have some purists complaining about the inefficiency of the
repeated tests, but is to my eyes expressive and reasonably clear.
STANDBACK I'M ABOUT TO PERFORM MAGIC:
for (i=0;i<H;i++) {
for (j=0;j<H;j++) {
if (x[i][j] == 1) {
goto AFTER_LOOP;
}
}
}
AFTER_LOOP:
// more code here
Thanks folks!
Tom
"Any references to Goto (an obscure Japanese admiral) are obscene,
unfit for your eyes and anyway don't mean what you think they do -
delete them" (notes on the Algol manual from a university course in
the 1970s).
I'm allergic to gotos - if I managed to write COBOL without goto for
many years, I think I can manage to write C without goto. (My primary
language these days is Java, which doesn't even have goto).
> I want to quit of both "for" loop whenever I find x[i][j]=1;
>
> Do you know how to do it?
>
> Right now, I am using the following code but I believe there should be
> a much more efficient way for this task.
I am not sure, but I doubt you mean efficient. If you do, that is
whole other ball game.
> flag=0;
> for (i=0;i<H;i++)
> {
> for (j=0;j<H;j++)
> if (x[i][j]==1)
> {
> flag=1;
> break;
> }
> if( flag)
> break
> }
I won't repeat the good suggestions but I'll add few more to think
about. You can get rid of your flag, because what you are looking for
acts like a flag:
for (i = 0; i < H; i++) {
for (j = 0; j < H && x[i][j] != 1; j++);
if (j < H)
break;
}
There is no shame in using a goto here. A simple and clear jump
forward is not going to confuse anyone:
for (i = 0; i < H; i++) {
for (j = 0; j < H; j++)
if (x[i][j] == 1)
goto outer_break;
}
outer_break:
The trouble with gotos is the temptation! You could be drawn into
using it for more than a double break and that is the start of a
slippery slope. I would not be happy with:
for (i = 0; i < H; i++) {
for (j = 0; j < H; j++)
if (x[i][j] == 1)
goto found;
}
/* code here to what to do when the element is not found */
found:
/* code here for a successful search */
especially if the "not found" code is long and complex.
Finally, you could put the search in a function. This becomes, for
me, the first choice solution if you have more than one of these
loop pairs. Even with only one I'd probably use it.
The trouble with giving you an example is that there are lots of
options (what type is x? do you need C99's VLAs? do you really need
the indexes or would a pointer to the found element do?). Anyway, one
simple version might look like this:
bool find_eq1(int (*x)[H], int *rowp, int *colp)
{
for (int i = 0; i < H; i++)
for (int j = 0; j < H; j++)
if (x[i][j] == 1) {
*rowp = i;
*colp = j;
return true;
}
return false;
}
which you'd use like this:
if (find_eq1(x, &i, &j))
/* ... */
[This uses C99 'for' loop syntax and needs #include <stdbool.h>.]
--
Ben.
> I'm allergic to gotos - if I managed to write COBOL without goto for
> many years, I think I can manage to write C without goto. (My primary
> language these days is Java, which doesn't even have goto).
What do you think break is, if not another word for goto?
B.
> "Any references to Goto (an obscure Japanese admiral) are obscene,
> unfit for your eyes and anyway don't mean what you think they do -
> delete them" (notes on the Algol manual from a university course in
> the 1970s).
>
> I'm allergic to gotos - if I managed to write COBOL without goto for
> many years, I think I can manage to write C without goto. (My primary
> language these days is Java, which doesn't even have goto).
That was written at a time when primitive language like BASIC and
FORTRAN 66 didn't have any decent control structures, and goto
statements had to be used to simulate control structures. Nowadays you
have languages like Java and C++ that provide "exceptions" which are
really the mother-fucking-goto-statement-from-hell.
And then there was the proof that any program can be written without
using "goto" - by labelling every statement, turning all control
structures into gotos, introducing a variable holding the variable,
and ending up with a program like
int label = 1;
for (;;) {
if (label == 1) { statement1; label = 2; }
else if (label == 2) { statement2; label = 3; }
else if (label == 3) { statement3; if (condition) label = 1; else
label = 4; } // That would be a simulated goto
...
}
If some article from the '70s causes you allergies, then maybe you
should seek medical help.
I recognise that, and I'm no great fan of break (or continue).
My suggested code used neither break nor continue.
> If some article from the '70s causes you allergies, then maybe you
> should seek medical help.
What makes you think my allergy comes from the article?
I've been programming in various languages for over 30 years, and I
found by experience very early on that goto was rarely useful and
could be, as the man said, harmful. I can't remember the last time I
used one.
> That was written at a time when primitive language like BASIC and
> FORTRAN 66 didn't have any decent control structures, and goto
> statements had to be used to simulate control structures. Nowadays you
> have languages like Java and C++ that provide "exceptions" which are
> really the mother-fucking-goto-statement-from-hell.
So that makes setjmp and longjmp... what? Demonic abominations?
Although I agree with every word you say (above), I defend your right to
say it!
Having said that, I am quite content to use break within switch, and
quite content to use continue in an otherwise empty loop.
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
>The trouble with gotos is the temptation! You could be drawn into
>using it for more than a double break and that is the start of a
>slippery slope. I would not be happy with:
>
> for (i = 0; i < H; i++) {
> for (j = 0; j < H; j++)
> if (x[i][j] == 1)
> goto found;
> }
> /* code here to what to do when the element is not found */
>found:
> /* code here for a successful search */
>
>especially if the "not found" code is long and complex.
If my not terribly reliable understanding is correct, variables
and labels are in different name spaces so you could write:
int found = 0;
for (i = 0; i < H; i++) {
for (j = 0; j < H; j++) {
if (x[i][j] == 1) {
found = 1;
goto found;
}
}
}
found:
if (found) {/* found stuff */}
else {/* not found stuff */}
I don't mind if you can't. :-)
Richard Harter, c...@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
It's not much to ask of the universe that it be fair;
it's not much to ask but it just doesn't happen.
At some level there is really just one loop conceptually, iterating
over a square set of elements in the 2-dimensional array x. So you
might try combining the two 'for()' statements to make a single
loop, as for example:
for( i = 0, j = 0; i < H; ++j < H || (j = 0, i++) ){
if( x[i][j] == 1 ) break;
}
The "next value" expression is a little clunky, but that's a
byproduct of C's operator set more than anything else.
Now that you mention it ...
I agree. I think the lengths people go to (no pun intended) to avoid a
simple goto statement is asinine. For a language without "named
breaks," I think this is the simplest construct. This is one of two
uses that I can think of where I find a goto as the simplest solution.
I don't believe the goto is inherently bad, but like any feature, can
be abused.
I've seen some god-awful code written because someone was allergic to
a particular programming construct (e.g., goto, do loops, break,
continue, threads, multiply inheritance, exceptions, recursive
mutexes, etc. not all are relevant to C, but you get my point). I once
saw some code written for Windows by a guy that railed against
threads. It was a mess of timer events, asynchronous I/O, and an
overly complex state machine, all to avoid creating a simple
background thread.
REH
As someone pointed out exceptions in Java are really just goto,
consider the two blocks
// statements that allocate ram/resources/etc
if (something() != OK) { goto error; }
if (somethingelse() != OK) { goto error; }
// ... and so on
return OK;
error:
// clean up code
return BAD;
Then compare that to
try {
something();
somethingelse();
} catch (exception e) {
// clean up
return BAD;
}
return OK;
How are they any diff [other than presentation]? "anti-goto" rules
are fairly stupid as any strict "anti-whatever" rule kinda omits the
possibility for ... exceptions to the rule ... :-)
I'm all against backwards goto in general [that's what continue is
for]. But forward goto's are perfectly fine provided they're used
when needed [exception handling and exiting a deeply nested loop being
two prime examples].
Tom
And, of course, the termination condition could be put within the
for loop, i.e.:
for(i = 0, j= 0;
(i < H) && (x[i][j] != 1);
(++j < H) || (j = 0, i++));
To get the true spirit of C it would be better to remove all of
the spaces and put the whole thing on one line.
for(i=0,j=0;(i<H)&&(x[i][j]!=1);(++j<H)||(j=0,i++));
....
An issue that OP does not raise is the place where he quits may
depend on whether he is doing a row major or column major search;
usually it will if there is more than 1 in the array. Sometimes
it is best to do a diagonal traversal or a subsquares traversal.
Diagonal traversals look like this:
0 1 3
2 4 6
5 7 8
And subsquares traversals look like this:
0 2 4
1 3 5
6 7 8
Obviously either pattern can be reflected along the main
diagonal. Writing the corresponding loops is left as a simple
exercise for the reader.
Also one can use a function to convert the search into a search
of a one dimensional array, but this ends up being rather
cumbersome in C.
Except that you have to add a test at every nested level which
ultimately slows it down. Why isn't a simple jump out of the loop
once you hit the particular exit condition sufficient?
Worse, your solution on exits AFTER the innermost for compound
statement is finished. What if he had
// inner loop
for (j = 0; j < H && !found; j++) {
if (x[i][j] == 1) { found = 1; }
x[i][j] += 5; // or whatever...
}
He'd now have to nest it
// inner loop
for (j = 0; j < H && !found; j++) {
if (x[i][j] == 1) {
found = 1;
} else {
x[i][j] += 5; // or whatever...
}
}
Yes, clearly that's much simpler than a simple goto out of the
nesting.
Tom
You could, but I don't think I'd bother. Because of the way I think
about loops, the natural test after the loop is
if (i < H) /* found what we wanted */
Another small worry I'd have is that you've labeled a position in the
source with a misleading name. OK, you only jump there when the item
is found, but I prefer to use neutral names to label location one can
simply arrive at.
<snip>
--
Ben.
int findOne(int**x, int H, int *ip, int *jp) {
int i,j;
for (i=0;i<H;i++) {
for (j=0;j<H;j++) {
if (x[i][j]==1) {
*ip = i;
*jp = j;
return 1;
}
}
}
return 0;
}
--
Fred K
>On Mar 5, 9:01=A0am, Mark Bluemel <mark.blue...@googlemail.com> wrote:
>> What makes you think my allergy comes from the article?
>>
>> I've been programming in various languages for over 30 years, and I
>> found by experience very early on that goto was rarely useful and
>> could be, as the man said, harmful. I can't remember the last time I
>> used one.
>
>As someone pointed out exceptions in Java are really just goto,
>consider the two blocks
>
> // statements that allocate ram/resources/etc
> if (something() !=3D OK) { goto error; }
> if (somethingelse() !=3D OK) { goto error; }
> // ... and so on
> return OK;
>error:
> // clean up code
> return BAD;
>
>
>Then compare that to
>
>try {
> something();
> somethingelse();
>} catch (exception e) {
> // clean up
> return BAD;
>}
>return OK;
>
>How are they any diff [other than presentation]? "anti-goto" rules
>are fairly stupid as any strict "anti-whatever" rule kinda omits the
>possibility for ... exceptions to the rule ... :-)
They work much the same, but the presentation is important. The
try/catch construction has strict limitations; the goto error
construction does not. My view is that java is meant for
drinking and never for coding. In some languages with exceptions
you can nest try/catch blocks and unwinding will be taken care of
automatically. This isn't true when using gotos for error
handling.
Incidentally, how are with simulating blocks with
do {...} while (0);
In your example you could write:
do {
if ((result = something()) == BAD) break;
if ((result = somethingelse()) == BAD) break;
} while(0);
if (result == BAD) {
/* clean up code */
} else {
/* Action code */
}
return result;
For some reason, many people get uptight about using blocks (I'm
using the term as a block of code that is not in a loop but can
be escaped from.) Oddly enough they are have no problem with
using a function as a block.
How do you stand on this issue?
>
>I'm all against backwards goto in general [that's what continue is
>for]. But forward goto's are perfectly fine provided they're used
>when needed [exception handling and exiting a deeply nested loop being
>two prime examples].
>
>Tom
Richard Harter, c...@tiac.net
Sniff. You omitted the smiley.
> On Fri, 05 Mar 2010 15:28:18 +0000, Ben Bacarisse
> <ben.u...@bsb.me.uk> wrote:
>
> Sniff. You omitted the smiley.
I am not good with smileys. I have tried, recently, to inject a few
in to my posts but I am not entirely happy with the results :-(
As a result, I probably come over as serious and ponderous about
things that I take with a pinch of salt. Sorry if that is the case.
To keep things light and topical, here is another single loop version
to ponder the merits of:
for (i = 0; i < H*H && x[i/H][i%H] != 1; i++);
I rather like it :-)
--
Ben.
>c...@tiac.net (Richard Harter) writes:
>
>> On Fri, 05 Mar 2010 15:28:18 +0000, Ben Bacarisse
>> <ben.u...@bsb.me.uk> wrote:
>>
>> Sniff. You omitted the smiley.
>
>I am not good with smileys. I have tried, recently, to inject a few
>in to my posts but I am not entirely happy with the results :-(
>
>As a result, I probably come over as serious and ponderous about
>things that I take with a pinch of salt. Sorry if that is the case.
>
>To keep things light and topical, here is another single loop version
>to ponder the merits of:
>
> for (i = 0; i < H*H && x[i/H][i%H] != 1; i++);
>
>I rather like it :-)
And well you should. :-)
You could make it more efficient (if I have the syntax right)
with
int **y; /* use appropriate type */
for (i = 0, y = (int **)x; i <HH && y[i] != 1; i++);
j = i%H; i /= H;
There is no end of good solutions. :-)
It's "break," of course.
If you equate every transfer of control with "goto," you are
confusing low-level implementation techniques with the language
structures they implement. Put it this way: If you think "break"
is "goto" (and I imagine you think of "continue" the same way),
what do you think of "return?" Of the function call operator?
Of "while" and "for" and "do" and "switch" and "if" and "else?"
Of the "?:" operator, particularly when the second and/or third
operands have side-effects? All of these cause control transfers,
sometimes more than one; are they therefore all "goto?"
--
Eric Sosman
eso...@ieee-dot-org.invalid
> On Fri, 05 Mar 2010 16:22:51 +0000, Ben Bacarisse
> <ben.u...@bsb.me.uk> wrote:
<snip>
>>To keep things light and topical, here is another single loop version
>>to ponder the merits of:
>>
>> for (i = 0; i < H*H && x[i/H][i%H] != 1; i++);
>>
>>I rather like it :-)
>
> And well you should. :-)
>
> You could make it more efficient (if I have the syntax right)
> with
>
> int **y; /* use appropriate type */
>
> for (i = 0, y = (int **)x; i <HH && y[i] != 1; i++);
> j = i%H; i /= H;
I think you intended to treat x as a 1-dimensional array, yes? If so,
you wanted to write:
int *y;
for (i = 0, y = x[0]; i < H*H && y[i] != 1; i++);
j = i%H; i /= H;
but that brings up another c.l.c FAP[1]: is indexing y from y[H]
onwards really permitted?
[1] Frequently Argued Point.
--
Ben.
One significant difference is that `goto' specifies the
target of the control transfer. Upon seeing `goto label' you
can hunt for `label' and know where execution will resume. But
when you see `throw new HissyFit()' all you know is that you're
going somewhere else. Where? Well, um, "it depends."
Another difference is that with `goto label', when control
arrives at `label' there's no additional information. "How did
I get here?" is unknown, unless the program is amenable to a
static analysis that reveals there's only one point of departure.
An exception carries a lot of information about its circumstances,
and that information is available to -- and manipulable by -- the
code at the `catch' point.
It seems to me that "someone" has oversimplified.
--
Eric Sosman
eso...@ieee-dot-org.invalid
<snip>
> To keep things light and topical, here is another single loop version
> to ponder the merits of:
>
> for (i = 0; i < H*H && x[i/H][i%H] != 1; i++);
This reminds me of a solution I once wrote to an exercise question that
used to bring quite a few panicking newbies to this group. The idea was
to write a program that could generate a diamond-shaped border, like this:
*
* *
* *
* *
*
to a runtime-specified arbitrary (but reasonable) size. My solution used
a single loop. Here it is (and, for the impatient, I've added a
preprocessed version at the end of this article):
#include <stdlib.h>
#include <stdio.h>
#define O int
#define B main
#define F char
#define U if
#define S atoi
#define C for
#define A putchar
#define T '*'
#define E ' '
#define D '\n'
#define c ==
#define o =
#define d ++
#define e return
#define r ||
O
B (
O k
, F
* v
[ ]
) {
O i
, j = 9
; U ( k > 1
) { j = S
( v [ 1
] ) ; }
U ( ! (
j > 0 )
) { j =
5 ; } U ( (
j & 1 ) c 0 ) {
d j ; } C (
i = 0 ;
i < j * j
; A ( i / j
c ( 3 * j
) / 2 -
( i % j + 1
) r i / j c j /
2 - i % j r
i / j c
j / 2 +
i % j r
i / j c
i % j -
j / 2 ? T
: E ) , i d
, i % j
c 0
? A
( D
) :
0 )
; e
0 ;
}
Here is the post-preprocessor version:
#include <stdlib.h>
#include <stdio.h>
int main(int k, char *v[]) { int i, j = 9; if(k > 1) { j = atoi(v[1]); }
if(!(j > 0)) { j = 5; } if((j & 1) == 0) { ++j; } for(i = 0; i < j * j;
putchar(i / j == (3 * j) / 2 - (i % j + 1) || i / j == j / 2 - i % j ||
i / j == j / 2 + i % j || i / j == i % j - j / 2 ? '*' : ' '), i++, i %
j == 0 ? putchar('\n') : 0) ; return 0; }
<gratuitous smiley snipped, thou bounder>
Usually I have code like
if ((err = blah()) != OK) goto ERROR;
So you can return "err" to the user. The only real downside is you
wouldn't know WHICH function call returned that error code. Which is
where I get more clever. In my code on GLIBC platforms when an error
occurs inside a deeper function I get a stacktrace and log it. Then
when the user dumps the error log they get a stack trace of every
error.
Most of the time that alone is sufficient to figure out the problem
without even firing up a debugger.
Tom
It's a fair cop.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
Yes (most of the time). They should have stakes driven
through their hearts -- but as has been pointed out here oft
and again, the C language itself doesn't use a stake ...
--
Eric Sosman
eso...@ieee-dot-org.invalid
This group is really helpful.
I learn a lot from your answers.
Best
Usually I have code like
if ((err = blah()) != OK) goto ERROR;
# char *k;
# ...
# ERROR: ; printf("Error in function %s code %u\n", k, err); return 0;
# k="No error"
# ...
# if ((k="blah()") && (err = blah()) != OK) goto ERROR;
> Hi all,
>
> I want to quit of both "for" loop whenever I find x[i][j]=1;
>
> Do you know how to do it?
>
> Right now, I am using the following code but I believe there should be a
> much more efficient way for this task.
>
> flag=0;
> for (i=0;i<H;i++)
> {
> for (j=0;j<H;j++)
> if (x[i][j]==1)
> {
> flag=1;
> break;
> }
> if( flag)
> break
> }
>
> Thanks
Well, you *could* use the "cascading break" :
*************/
for (i=0; i < I; i++) {
for (j=0; j < J; j++) {
if (stuff[i][j] == 1) break;
}
if (j != J) break;
}
if (i != I) { found(); }
else { not_found(); }
/*************************
It is cleaner than using a flag variable; and the compiler
might optimize it away (... to a goto ...);
, but personally I find either a goto or quick return
more readable.
HTH,
AvK
Yes, and I considered doing that. I didn't because using the
'break' form seems like a better expression of how OP
conceptualizes the problem.
> To get the true spirit of C it would be better to remove all of
> the spaces and put the whole thing on one line.
>
> for(i=0,j=0;(i<H)&&(x[i][j]!=1);(++j<H)||(j=0,i++));
>
Ohnowyou'rejustbeingsilly.
> [snip additional unrelated comments]
> On Fri, 05 Mar 2010 16:22:51 +0000, Ben Bacarisse
> <ben.u...@bsb.me.uk> wrote:
>
>>c...@tiac.net (Richard Harter) writes:
>>
>>> On Fri, 05 Mar 2010 15:28:18 +0000, Ben Bacarisse
>>> <ben.u...@bsb.me.uk> wrote:
>>>
>>> Sniff. You omitted the smiley.
>>
>>I am not good with smileys. I have tried, recently, to inject a few
>>in to my posts but I am not entirely happy with the results :-(
>>
>>As a result, I probably come over as serious and ponderous about
>>things that I take with a pinch of salt. Sorry if that is the case.
>>
>>To keep things light and topical, here is another single loop version
>>to ponder the merits of:
>>
>> for (i = 0; i < H*H && x[i/H][i%H] != 1; i++);
>>
>>I rather like it :-)
>
> And well you should. :-)
>
> You could make it more efficient (if I have the syntax right)
> with
>
> int **y; /* use appropriate type */
>
> for (i = 0, y = (int **)x; i <HH && y[i] != 1; i++);
> j = i%H; i /= H;
No need to have/use an auxiliary variable y:
for( i = 0; i < H*H && ((int*)&x)[i] != 1; i++ );
> There is no end of good solutions. :-)
No doubt. Now if there were just some way of getting people
to agree on which ones are the good ones... :)
Isn't it generally agreed that the Standard expects 'y = x[0]' not to
(have to) work, but 'y = (int*)x' or 'y = (int*)&x' to work? Is
there any real contention on what the Standard expects on this
particular point (even though there is debate about how well it
says it)?
> Ben Bacarisse <ben.u...@bsb.me.uk> writes:
<snip>
>> int *y;
>> for (i = 0, y = x[0]; i < H*H && y[i] != 1; i++);
>> j = i%H; i /= H;
>>
>> but that brings up another c.l.c FAP[1]: is indexing y from y[H]
>> onwards really permitted?
>>
>> [1] Frequently Argued Point.
>
> Isn't it generally agreed that the Standard expects 'y = x[0]' not to
> (have to) work, but 'y = (int*)x' or 'y = (int*)&x' to work? Is
> there any real contention on what the Standard expects on this
> particular point (even though there is debate about how well it
> says it)?
I am surprised you think anything like this could be "generally
agreed" :-)
I toyed with using a pointer that unambiguously referred to the whole
array (I'd have gone for (void *)x) but I did not want to invite the
debate by including a cast that some might think is not needed. I
failed of course, since here we are again.
--
Ben.
> Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> writes:
>
>> Ben Bacarisse <ben.u...@bsb.me.uk> writes:
> <snip>
>>> int *y;
>>> for (i = 0, y = x[0]; i < H*H && y[i] != 1; i++);
>>> j = i%H; i /= H;
>>>
>>> but that brings up another c.l.c FAP[1]: is indexing y from y[H]
>>> onwards really permitted?
>>>
>>> [1] Frequently Argued Point.
>>
>> Isn't it generally agreed that the Standard expects 'y = x[0]' not to
>> (have to) work, but 'y = (int*)x' or 'y = (int*)&x' to work? Is
>> there any real contention on what the Standard expects on this
>> particular point (even though there is debate about how well it
>> says it)?
>
> I am surprised you think anything like this could be "generally
> agreed" :-)
Well, I did say "generally agreed", not "universally agreed."
To be more specific, isn't it essentially universally agreed that
using '(T*)&x' will get an array for the entire region
occupied by x, even if x is a multi-dimensional array? That
assertion seems pretty uncontroversial.
> I toyed with using a pointer that unambiguously referred to the whole
> array (I'd have gone for (void *)x) but I did not want to invite the
> debate by including a cast that some might think is not needed. I
> failed of course, since here we are again.
What, you're trying to say that there is debate about whether
or not a debate exists? In comp.lang.c? Preposterous!
> Ben Bacarisse <ben.u...@bsb.me.uk> writes:
>
>> Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> writes:
>>
>>> Ben Bacarisse <ben.u...@bsb.me.uk> writes:
>> <snip>
>>>> int *y;
>>>> for (i = 0, y = x[0]; i < H*H && y[i] != 1; i++);
>>>> j = i%H; i /= H;
>>>>
>>>> but that brings up another c.l.c FAP[1]: is indexing y from y[H]
>>>> onwards really permitted?
>>>>
>>>> [1] Frequently Argued Point.
>>>
>>> Isn't it generally agreed that the Standard expects 'y = x[0]' not to
>>> (have to) work, but 'y = (int*)x' or 'y = (int*)&x' to work? Is
>>> there any real contention on what the Standard expects on this
>>> particular point (even though there is debate about how well it
>>> says it)?
>>
>> I am surprised you think anything like this could be "generally
>> agreed" :-)
>
> Well, I did say "generally agreed", not "universally agreed."
>
> To be more specific, isn't it essentially universally agreed that
> using '(T*)&x' will get an array for the entire region
> occupied by x, even if x is a multi-dimensional array? That
> assertion seems pretty uncontroversial.
It does to me too, but I have an unsettling feeling that there was
some dissent form that view. Maybe I am misremembering.
<snip>
--
Ben.
You keep making puns like that and you're going to be in a heap of
trouble.
--
Larry Jones
Just when I thought this junk was beginning to make sense. -- Calvin
can Java's break jump backwards? Can it be used outside a loop? Does
it restart execution at a named label? Because if not then Java's
break isn't goto.
C's break isn't goto either.
> > "Any references to Goto (an obscure Japanese admiral) are obscene,
> > unfit for your eyes and anyway don't mean what you think they do -
> > delete them" (notes on the Algol manual from a university course in
> > the 1970s).
>
> > I'm allergic to gotos - if I managed to write COBOL without goto for
> > many years, I think I can manage to write C without goto. (My primary
> > language these days is Java, which doesn't even have goto).
>
> That was written at a time when primitive language like BASIC and
> FORTRAN 66 didn't have any decent control structures, and goto
> statements had to be used to simulate control structures.
yes. There are few places where goto is needed now (I'd be fairly
happy with a goto to solve the OPs problem).
> Nowadays you
> have languages like Java and C++ that provide "exceptions" which are
> really the <expletive>-goto-statement-from-hell.
I seem to be spending most of my sunday morning writing "no
$CONTROL_STRUCTURE isn't a goto". Exceptions aren't gotos.
> And then there was the proof that any program can be written without
> using "goto" - by labelling every statement, turning all control
> structures into gotos, introducing a variable holding the variable,
> and ending up with a program like
>
> int label = 1;
> for (;;) {
> if (label == 1) { statement1; label = 2; }
> else if (label == 2) { statement2; label = 3; }
> else if (label == 3) { statement3; if (condition) label = 1; else
> label = 4; } // That would be a simulated goto
> ...
>
> }
>
> If some article from the '70s causes you allergies, then maybe you
> should seek medical help.
"Bohm and Jacopini Considered Harmful"
> >> What makes you think my allergy comes from the article?
>
> >> I've been programming in various languages for over 30 years, and I
> >> found by experience very early on that goto was rarely useful and
> >> could be, as the man said, harmful. I can't remember the last time I
> >> used one.
>
> >As someone pointed out exceptions in Java are really just goto,
> >consider the two blocks
I've not programmed in Java but if Java's exceptions are anything like
C++ then they aren't gotos (what *is* it with Java programmers? Are
they victims of Worf's hypothesis- they don't have a gotos in their
langauge therefore they can't think about them? "oh goto that's like,
er, break or throwing an exception"). C++ are strictly limited in
where they can pass control to. They can pass control out of the
current function (C gotos can't do this) they pass data. In some ways
they are like a magic function call. You don't think the "passing
data" bit is really un-goto-like?
> > // statements that allocate ram/resources/etc
> > if (something() !=3D OK) { goto error; }
> > if (somethingelse() !=3D OK) { goto error; }
> > // ... and so on
> > return OK;
> >error:
> > // clean up code
> > return BAD;
>
> >Then compare that to
>
> >try {
> > something();
> > somethingelse();
> >} catch (exception e) {
> > // clean up
> > return BAD;
> >}
> >return OK;
>
> >How are they any diff [other than presentation]?
that "e" expression is the giveaway
sorry, what's a "block"? Ah you're using the while just so you use a
break? Looks a bit icky to me. I think I'd rather have gotos and be
honest about it.
> How do you stand on this issue?
>
> >I'm all against backwards goto in general [that's what continue is
> >for].
I'm not a fan of continue. Except for empty loops.
while ((ch = getchar()) == SPACE)
continue;
Yes, but is that really the point that matters? break is good because it
is like a very restricted form of goto, but it is also bad because any
sort of goto has problems.
In a language (or programming style) without break and goto one can
make strong arguments about the behaviour of loops. After
while (E) { S; }
one can assert that !E is true (there may not be an "after" of
course). Banning continue and non-terminal return statements also
simplifies the reasoning about the interaction of S and E.
Some argue that the problems of carefully used gotos are mitigated by
the presence of labels that announce the potential for trouble,
whereas break silently interferes with such reasoning. Others argue
that well-used breaks can be folding into such reasoning without much
trouble. Others would say that reasoning about programs is hopeless
in C, so who cares what constructs one uses provided they get the job
done. (This are very far from an exhaustive list of views!)
I sometimes get the feeling that programmers treat this issue like
football (soccer) supporters. One team's fans are jeering "break is a
goto" and the other side is signing "break is a structured
construct"[1]. Of course there are more than two teams, but which
team one supports is less interesting than why one supports it. Maybe
we could have a bit more why when these polarising topics come up?
This is not really aimed at anyone in particular. I just picked a
place to inject a comment almost at random.
[1] These chants may need some work.
--
Ben.
>On 5 Mar, 15:43, c...@tiac.net (Richard Harter) wrote:
>> Incidentally, how are with simulating blocks with
>> do {...} while (0);
>>
>> In your example you could write:
>>
>> do {
>> if ((result = something()) == BAD) break;
>> if ((result = somethingelse()) == BAD) break;
>> } while(0);
>> if (result == BAD) {
>> /* clean up code */
>> } else {
>> /* Action code */
>> }
>> return result;
>>
>> For some reason, many people get uptight about using blocks (I'm
>> using the term as a block of code that is not in a loop but can
>> be escaped from.) Oddly enough they are have no problem with
>> using a function as a block.
>
>sorry, what's a "block"? Ah you're using the while just so you use a
>break? Looks a bit icky to me. I think I'd rather have gotos and be
>honest about it.
Well there you are; you are one of the up tight ones. :-)
In some languages, not C of course, you can escape (break) from a
simple delimited block. If you could do this in C you could
write:
{
if ((result = something()) == BAD) break;
if ((result = somethingelse()) == BAD) break;
}
if (result == BAD) {
/* clean up code */
} else {
/* Action code */
}
return result;
I've used languages where you could do the equivalent of this
kind of code. The code is cleaner because "break" is a more
sharply defined transfer than "goto" and because it doesn't
require a label. Where this construct is useful is when you have
a series of tests, i.e., you are filtering the input.
Care to explain what "use a stake" means here? I tried to look it up,
with not much success.
Thanks,
lacos
It's a pun. Eric is playing on the oft quoted phrase "C does not use
a stack". Hence Lawrence's "heap" pun in reply.
Eric's did register on my humour meter but Lawrence is talking a load
of mallocs.
--
Ben.
(As you know) that's not much of a deduction. So what advantage can
similar reasoning be expected to give in imperative programming? (Not
functional programming which is another matter.) I've seen people
write about advantages of certain control structures but I've never
come across an explanation of the principles, if there are any.
For example the most general imperative loop construct would be of the
form
for (;;) {
<code>
if (c1) break;
<more code>
if (c2) break;
<even more code>
if (c3) break;
<etc>
}
Top and bottom decision loops as well as arbitrary mid decisions can
all be expressed using such a control structure. Is there something
about that form which inhibits reasoning?
> Banning continue and non-terminal return statements also
> simplifies the reasoning about the interaction of S and E.
I'm glad to hear it but in what way or ways does *continue* work
against reasoning?
I guess you are referring to mid-routine return statements. They can
return no value or a value of the wrong type. Any other problems with
them from the point of view of reasoning?
James
>On 7 Mar, 14:16, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>...
>> In a language (or programming style) without break and goto one can
>> make strong arguments about the behaviour of loops. =A0After
>>
>> =A0 while (E) { S; }
>>
>> one can assert that !E is true (there may not be an "after" of
>> course).
>
>(As you know) that's not much of a deduction. So what advantage can
>similar reasoning be expected to give in imperative programming? (Not
>functional programming which is another matter.) I've seen people
>write about advantages of certain control structures but I've never
>come across an explanation of the principles, if there are any.
>
>For example the most general imperative loop construct would be of the
>form
>
> for (;;) {
> <code>
> if (c1) break;
> <more code>
> if (c2) break;
> <even more code>
> if (c3) break;
> <etc>
> }
>
>Top and bottom decision loops as well as arbitrary mid decisions can
>all be expressed using such a control structure. Is there something
>about that form which inhibits reasoning?
One issue is that the termination condition is
c1 || c2 || c3 ...
In other words we know that one of them is true but we don't know
which one. This may not matter.
Another issue is that the breaks can be buried with nested code.
>
>
>> =A0Banning continue and non-terminal return statements also
>> simplifies the reasoning about the interaction of S and E.
>
>I'm glad to hear it but in what way or ways does *continue* work
>against reasoning?
>
>I guess you are referring to mid-routine return statements. They can
>return no value or a value of the wrong type. Any other problems with
>them from the point of view of reasoning?
>
>
>James
Richard Harter, c...@tiac.net
>c...@tiac.net (Richard Harter) writes:
>>In some languages, not C of course, you can escape (break) from a
>>simple delimited block. If you could do this in C you could
>>write:
>> {
>> if ((result = something()) == BAD) break;
>> if ((result = somethingelse()) == BAD) break;
>> }
>>
>> if (result == BAD) {
>
> if
> ( ( result = something() ) == BAD )||
> ( result = somethingelse() )== BAD ))
> {
Well yes, but I don't think it generalizes.
Okay, thanks :) I got the "heap of trouble" (even without understanding
the stack/stake pun) and also your malloc()'s/bollocks pun. I even
considered shortly what some witty response to Lawrence's pun might be,
with "stack" in it. I was completely oblivious to the fact that the
original pun ran with "stack" already. "stake" doesn't rhyme with
"stack" when pronounced, and I didn't notice the eye rhyme(?).
http://en.wikipedia.org/wiki/Eye_rhyme
Thanks,
lacos
> On 7 Mar, 14:16, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> ...
>> In a language (or programming style) without break and goto one can
>> make strong arguments about the behaviour of loops. After
>>
>> while (E) { S; }
>>
>> one can assert that !E is true (there may not be an "after" of
>> course).
>
> (As you know) that's not much of a deduction. So what advantage can
> similar reasoning be expected to give in imperative programming?
I was simplifying and obviously went too far. You also have a loop
invariant, P, and it is this along with !E that forces the
post-condition, R, that the code intends to set up. On its own P
says very little but P /\ !E => R.
> (Not
> functional programming which is another matter.) I've seen people
> write about advantages of certain control structures but I've never
> come across an explanation of the principles, if there are any.
>
> For example the most general imperative loop construct would be of the
> form
>
> for (;;) {
> <code>
> if (c1) break;
> <more code>
> if (c2) break;
> <even more code>
> if (c3) break;
> <etc>
> }
>
> Top and bottom decision loops as well as arbitrary mid decisions can
> all be expressed using such a control structure. Is there something
> about that form which inhibits reasoning?
That one is not too bad because it is structured. It means
do {
<code>
if (!c1) {
<more code>
if (!c2) {
<even more code>
if (!c3) {
<etc>
}
}
}
} while (!c1 && !c2 && !c3);
(barring side-effects in the ci). The breaks imply a nesting that
complicates the reasoning but that is not the fault of the break. If
the loop has to be this complex because that is what is needed then
the break form is just a neater way to write it.
The problems come when break is used in far less structured ways. One
could argue that the problem is then not the break but the fact that
the code is a mess, and I'd probably go along with that.
Well-organised uses of break don't cause a lot of trouble.
>> Banning continue and non-terminal return statements also
>> simplifies the reasoning about the interaction of S and E.
>
> I'm glad to hear it but in what way or ways does *continue* work
> against reasoning?
This is likely to come out all hand-waving... When continue is used
in messy ways, for example:
while (E) {
if (C1) {
S1;
if (C2) {
S2;
continue;
}
}
S3;
}
you end up having to roll up lots of steps in the reasoning so as to
reason about the whole loop body. You can't use the usual rules about
if statements because the continue ties the inner if to the semantics
of the whole loop body.
> I guess you are referring to mid-routine return statements. They can
> return no value or a value of the wrong type.
Yes, by 2non-terminal" I meant mid-function return statements but I
don't follow what you mean here.
> Any other problems with
> them from the point of view of reasoning?
They have the same effect as on the continue example except the linkage
is to the enclosing function.
--
Ben.
> Ben Bacarisse <ben.u...@bsb.me.uk> writes:
>>> for (;;) {
>>> <code>
>>> if (c1) break;
>>That one is not too bad because it is structured.
>
> ... if you make the assumption that <code> has one entry and
> one exit, but it was not excluded that <code> might contain
> even more break statements.
I think it was by context, but I see your point. If some says "what
about this pattern of break usage?" I think it is reasonable to assume
they mean these are all the break statements.
I agree that in practise one might have to check, but that's true even
if coding style excludes break.
<snip>
--
Ben.
Hey, let's not cast aspersions.
--
Larry Jones
It seems like once people grow up, they have no idea what's cool. -- Calvin
... nor make it an automatic response to dish out this
type of static.
--
Eric Sosman
eso...@ieee-dot-org.invalid
if we could break out of this loop it would be good, but we can't while
the coding standards forbid it.
--
Flash Gordon
Oi! Can't you take an 'int?
--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within
In languages which support exceptions they generally break the
apparent flow of control by jumping forward to a handler. There seems
to be an analog between exceptions, break and return. All jump forward
to a well-defined point. So I'm not sure there is much to be gained by
outlawing embedded break statements. In fact ISTM sensible and natural
to add the ability to break out of more than one level of control
structure (the OP's initial query). For example, if a for loop was
named "row" something like
break row
would break out of as many nested structures as necessary to continue
after the "row" loop.
I'm not suggesting a change to C, merely stating an opinion on a
programming language design issue.
James
> Flash Gordon wrote:
>> Eric Sosman wrote:
>>> On 3/8/2010 11:22 AM, lawrenc...@siemens.com wrote:
>>>> Ben Bacarisse<ben.u...@bsb.me.uk> wrote:
>>>>>
>>>>> Eric's did register on my humour meter but Lawrence is talking a load
>>>>> of mallocs.
>>>>
>>>> Hey, let's not cast aspersions.
>>>
>>> ... nor make it an automatic response to dish out this
>>> type of static.
>>
>> if we could break out of this loop it would be good, but we can't while
>> the coding standards forbid it.
>
> Oi! Can't you take an 'int?
I think a pointer might help us understand the long and short of it.
Regards,
David Bolt
--
Team Acorn: www.distributed.net OGR-NG @ ~100Mnodes RC5-72 @ ~1Mkeys/s
openSUSE 11.0 32b | | | openSUSE 11.3M3 32b
openSUSE 11.0 64b | openSUSE 11.1 64b | openSUSE 11.2 64b |
TOS 4.02 | openSUSE 11.1 PPC | RISC OS 4.02 | RISC OS 3.11
> On 5 Mar, 12:08, Tom St Denis <t...@iahu.ca> wrote:
> > =A0 =A0 =A0 =A0 =A0goto AFTER_LOOP;
> "Any references to Goto (an obscure Japanese admiral) are obscene,
> unfit for your eyes and anyway don't mean what you think they do -
> delete them" (notes on the Algol manual from a university course in
> the 1970s).
Well, yeah. And where is Algol now? Just over a hundred light years
away, and long may it stay there.
Richard
> On Monday 08 Mar 2010 23:34, while playing with a tin of spray paint,
> Richard Heathfield painted this mural:
>
> > Flash Gordon wrote:
> >> Eric Sosman wrote:
> >>> On 3/8/2010 11:22 AM, lawrenc...@siemens.com wrote:
> >>>> Ben Bacarisse<ben.u...@bsb.me.uk> wrote:
> >>>>>
> >>>>> Eric's did register on my humour meter but Lawrence is talking a load
> >>>>> of mallocs.
> >>>>
> >>>> Hey, let's not cast aspersions.
> >>>
> >>> ... nor make it an automatic response to dish out this
> >>> type of static.
> >>
> >> if we could break out of this loop it would be good, but we can't while
> >> the coding standards forbid it.
> >
> > Oi! Can't you take an 'int?
>
> I think a pointer might help us understand the long and short of it.
IMO, this entire argument is null and void.
Richard
... serving only to block progress, to limit the scope
of endeavor, to foul the nest. Participants are dys-functional
and deserve to be switched.
--
Eric Sosman
eso...@ieee-dot-org.invalid
In that case we should shift onto another topic.
As if...
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
While I knew that the "Standard expects 'y = x[0]' not to (have to)
work", I didn't know
that "it essentially universally agreed that using '(T*)&x' will get
an array for the entire region occupied by x, even if x is a multi-
dimensional array". I don't have anything against it and it is not my
intention to reopen a debate on a F.A.P. but, just to improve my
knowledge on the Standard, I would like to know from what part(s) of
it that fact can be deduced. I confess that I don't understand much of
what the standard says about pointer conversions.
Could you please explain or give links to previous discussions about
this?
thanks a lot!
I don't have any links to previous discussions (perhaps a
search engine could provide some), but here is my explanation
(or rationalization, depending on one's point of view).
An array identifier just by itself is converted to a pointer to
the array's first element -- 'a == &a[0]', and not just equal but
definitionally equal, as I believe most people see it. The array
name 'a' must be usable to access the entire array of 'a', and
therefore so must '&a[0]' (or so the reasoning goes). Similar
reasoning (not identical reasoning, but similar) applies to the
address of any particular element of 'a' -- 'a+i == &a[i]', again
not just equal but definitionally equal (again AIBMPSI). So for
a two-dimensional array 'x[M][N]', 'x[1] == &x[1][0]' can access
all of "the array x[1]" but not (definedly) access any of "the
array x[2]". (Notice the difference between English and C. In
English 'x[1]' means "the array x[1]", whereas in C 'x[1]' means
"a pointer to the first element of the array x[1]". But it's
still true that that pointer can access all of "the array x[1]".)
So, reasoning by analogy with the one-dimensional array case, we
conclude that using an N-1 dimensional index, and no address
operator, is the same as using an N dimensional index _with_ an
address operator, which must be able to access the whole
one-dimensional array (with the first N-1 dimensions fixed,
varying just the last index). That assumption, or conclusion if
you will, is wired very deeply in the minds of all long term
C programmers.
The question of what happens with the higher dimensions proceeds
by analogy with what simpler array indexing does. Suppose
again we have two-dimensional array 'x[M][N]'. We expect the
pointer value of 'x', which is '&x[0]', to be able to access
each of the elements in 'x', because that's how array indexing
works. The elements of the array 'x' are themselves arrays,
but that doesn't change the reasoning about what can be accessed;
since 'x' is an array, using 'x' (or '&x[0]' which is the same
thing) ought to be able to access all of the array 'x'. Again
this is just how array indexing works in C.
Now we get to the $64 question -- what happens when such a
pointer value is converted to another type? As far as I know,
and I've never seen any text in any official document that
contradicts this, converting a pointer from one type to
another allows access to exactly the same region of storage
as the original pointer (assuming that there are no alignment
problems, and not counting any "fractional objects" that
might result when converting to a type whose size does not
evenly divide the amount of storage accessible using the
pre-conversion pointer type). This rule is not spelled out
in the Standard, and least not clearly enough so I can
identify any text that does. Despite that, as a practical
matter I think everyone takes it as a working assumption,
otherwise how could things like memcpy() or qsort() work?
If you believe this rule, you believe that doing '(T*)x' or
'(T*)&x[0]' allow access to all the storage occupied by 'x'.
Finally, the last case, '&x', is the easiest. We know for at
least one case, namely, '(char*)&x', that this pointer conversion
must allow access to all the bytes that make up "the entire array
x". (Again 'x' is a two-dimensional array 'x[M][N]', but the
same conclusion holds for arrays of higher dimensions.) Since
'(char*)&x' must be able to access all of "the array x", the most
obvious and sensible conclusion, absent specific text in the
Standard to the contrary, is that '(T*)&x' also must be able to
access all memory occupied by x (again taking into account
alignment and "fractional object" issues, but those aren't an
issue when we are converting to the sub-most element type of the
array whose address we are converting).
To restate what I said at the beginning, most of this isn't stated
explicitly in the Standard. But it is the reasoning that I use, and
I think that reasoning rests only on specific statements made in the
Standard and on common working assumptions held (at least for
practical purposes) by every C programmer I know or whose views on
the subject I'm aware of.