Understanding the harmfulness of goto statement referring to Edsger Dijkstra's Journal Paper of ACM-1968

There has been a vicious circle in the scientific community for years. Researchers and PhD students need to publish papers to secure funding or prepare for their thesis defence, and publishing is increasingly costly (many thousands of euros to submit a paper in leading journals).

As the number of publications influences funding renewal and the reputation of the lab, researchers are driven to produce more publications, often of lesser quality and richness of content. Reviewers, who are compensated for their work, may also benefit from reviewing more papers.

This has driven the quality downward ➜ The system is largely broken.


Nope — that was the whole article at the time. You'll remark that he wrote

I now submit my considerations for publication because in very recent discussions in which the subject turned up, I have been urged to do so.

Dijkstra's decision to publish the letter was possibly influenced by discussions with colleagues which likely took place within his professional circle. At the time there was the famous "Tuesday Afternoon Club," a seminar group where Dijkstra and his peers rigorously scrutinised scientific papers and discussed various aspects of computer science​.

If you read Edsger W. Dijkstra: Brilliant, colourful, and opinionated you'll see they mention

Many of Dijkstra’s papers, often just a few pages long, are the source of new research areas.

and he was known for these "short pieces" breaking new grounds and triggering more debates and research, progressing the domain - in the article you'll see as well

He wrote his articles in a unique style characterised by conciseness, economy of argument, and clarity of exposition. Each sentence was carefully chiselled. Each paragraph was striking.

You'll also read the story about the famous "Tuesday Afternoon Club".

The "concision and economy of argument" makes it harder to decode if you miss the formal culture (mathematical and computer theory) that was in vogue at the time.

I had no idea about the nominal paper size of Journal Paper of that time. I have been involved with Conference/Journal Paper activities from 1997 after my joining with a Technical University leaving behind Engineering Field activities.

I did read the quoted excerpt several times and inferred that Dijkstra was continually encouraged by his colleagues to publish his serious thoughts on the issue that we are discussing now.

All the bove characteristic features of Dijkstra's paper as you have eloquently described were in my understanding to some extent; but, I could not put them into writing due to poor vocabularies; however, I managed to use the term "condensed" to mean some part of that.

That again goes inline with P.J.Erret's (the Technical Manager of GEC Kidsgrove, UK under whom we took Training in 1979) remark that a learner at the level of knee cannot be lifted upto head.

Well, there was no Internet. If you wanted to have a flame war about programming style, you had to phrase it in cs/math “word salad” and see if some journal would publish it…

(This is a more serious comment than it ought to be.)

1 Like

yeah - usenet and BBS was late 70s - 10 years later than this article (ARPANET started in the US in 1969)

1 Like

Is it fair to judge the scientific understanding of that time using today's standards?

When we read Karl Popper, we see how rigorously and openly he criticized all the leading philosophers, particularly Karl Marx—some might call him (Popper) notorious; but, he is one of the most influential philosophers of the 20th century. Karl Marx was right in his time and for a long period afterward; now, he seems defamed (as I have inferred from the studies of Popper) due to drastic changes in political economy and technological development. edit.

ACM is an esteemed journal that continues to maintain its influence in the computing field worldwide.

Hum... Marx's critique of capitalism highlighted issues such as exploitation, class struggle, and economic inequality, which were relevant during the industrial revolution and continue to resonate today but the practical implementation of Marxist ideas in various forms of socialism and communism has had "mixed results" (to say the least) with significant failures (Soviet Union, Mao Zedong's china, many Eastern European countries, Cambodia (under the Khmer Rouge / Pol Pot's regime).

I think Karl Marx is "defamed" as you put it because of the significant human (millions of deaths and suffering) and economic costs related too practical application of Marxist principles and how reality diverged from the theoretical ideals.

Let's keep the discussion on the scientific side, politics is for another forum :slight_smile:

3 Likes

That is exactly what Karl Popper has said in his pilosophical essays on the Captial of Karl Marx. Since when are you a follower of Karl Popper? :smiley:

Sorry! It is not I who says so; it is that what I have inferred from Karl Popper's works. I am editing my post.

I am a Communist and then turned into a Socialist and now trying to be a balanced entity with ethics, democracy, and science.

then I agree with Karl Popper on this but not on everything...

Popper's criterion of falsifiability as the demarcation between science and non-science is somewhat outdated for me — cf the role of historical and sociological factors on how science progresses (➜ Kuhn's work about paradigm shifts and scientific revolutions - Thomas Kuhn (Stanford Encyclopedia of Philosophy)) or Bayesianism (https://www.strevens.org/research/simplexuality/Bayes.pdf) and other probabilistic approaches which to some degree influences modern research such as in the quantum computing domain.

1 Like

use of goto in 8ed Unix cmds

300.c:			goto loop;
300.c:	goto loop;
300s.c:			goto loop;
300s.c:	goto loop;
450.c:			goto loop;
450.c:	goto loop;
512restor.c:			goto usage;
512restor.c:			goto getvol;
512restor.c:			goto newvol;
512restor.c:			goto newvol;
512restor.c:			goto newvol;
512restor.c:			goto rbits;
512restor.c:						goto newvol;
512restor.c:				goto again;
512restor.c:					goto done;
512restor.c:		goto checkdone;
512restor.c:				goto ragain;
512restor.c:				goto ragain;
512restor.c:				goto ragain;
512restor.c:				goto ragain;
512restor.c:			goto finish;
512restor.c:	goto start;
512restor.c:			goto eloop;
512restor.c:					goto eloop;
512restor.c:				goto loop;
512restor.c:				goto loop;
512restor.c:				goto loop;
512restor.c:			goto found;
512restor.c:		goto next;
ac.c:					goto skip;
ac.c:				goto skip;
apply.c:			goto Toofew;
ar.c:				goto cp;
ar.c:					goto cp;
ar.c:				goto sk;
arcv.c:		goto out;
arcv.c:	goto loop;
arff.c:			goto found;
arff.c:				goto found;
arff.c:		goto overwrite;
arff.c:			goto overwrite;
ascii.c:			goto Done;
bad144.c:			goto found;
basename.c:				goto output;
cal.c:		goto xlong;
cal.c:		goto badarg;
cal.c:		goto badarg;
cal.c:		goto badarg;
cc.c:		goto nocom;
cc.c:			goto assemble;
cc.c:			goto compile;
chmod.c:		goto dup;
chmod.c:		goto dup;
cmp.c:		goto narg;
cmp.c:		goto narg;
cmp.c:		goto barg;
cmp.c:		goto barg;
cmp.c:			goto earg;
cmp.c:			goto earg;
cmp.c:		goto loop;
cmp.c:		goto earg;
cmp.c:		goto earg;
cmp.c:	goto loop;
cpio.c:				goto accerr;
cpio.c:				goto ckverbose;
cpio.c:		goto ret;
cpio.c:				goto again;
cpio.c:				goto again;
cpio.c:	if (c==scc) goto caseq;
cpio.c:		goto again;
ctags.c:	gotone,				/* found a func already on line	*/
ctags.c:					goto usage;
ctags.c:	number = gotone = midtoken = inquote = inchar = incomm = FALSE;
ctags.c:		if (!level && !inquote && !incomm && gotone == FALSE) {
ctags.c:						gotone = f;	/* function */
ctags.c:			number = gotone = midtoken = inquote = inchar = FALSE;
ctags.c:					goto ret;
ctags.c:			gotone = TRUE;
ctags.c:			goto ret;
ctags.c:		goto badone;
ctags.c:		goto badone;
ctags.c:		goto badone;
ctags.c:		goto ret;
ctags.c:		goto badone;
ctags.c:				goto ret;
ctags.c:		else if (!iswhite(c) && !firsttok) goto badone;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:				goto cloop;
dd.c:		goto loop;
dd.c:	goto loop;
dd.c:			goto true;
dd.c:		goto out;
dd.c:		goto out;
deroff.c:			goto again;
deroff.c:		goto comx; 
deroff.c:			goto comx; 
deroff.c:		goto comx; 
deroff.c:				if(C == '.')goto com;
deroff.c:			goto comx; 
deroff.c:		goto comx; 
deroff.c:			goto sw;
du.c:				goto ret;
du.c:				goto ret;
du.c:				goto ret;
dumpdir.c:			goto finish;
dumpdir.c:			goto found;
dumpdir.c:	goto start;
dumpdir.c:			goto eloop;
dumpdir.c:					goto eloop;
dumpdir.c:				goto loop;
dumpdir.c:				goto loop;
expand.c:			goto bad;
expand.c:			goto bad;
fgrep.c:			goto out;
fgrep.c:	cgotofn();
fgrep.c:				goto nstate;
fgrep.c:						goto istate;
fgrep.c:				else goto nstate;
fgrep.c:				goto nomatch;
fgrep.c:			if (vflag) goto succeed;
fgrep.c:cgotofn() {
fgrep.c:					if (s->inp == 0) goto nenter;
fgrep.c:						goto nenter;
fgrep.c:			if (s->inp == 0) goto enter;
fgrep.c:				goto enter;
fgrep.c:			goto loop;
fgrep.c:		goto nword;
fgrep.c:		goto init;
fgrep.c:				goto floop;
fgrep.c:				goto floop;	/* state = f(state) */
fgrep.c:			goto cloop;
file.c:		goto spcl;
file.c:		goto out;
file.c:		goto exec;
file.c:		goto exec;
file.c:		goto out;
file.c:		goto out;
file.c:		goto out;
file.c:		goto out;
file.c:		goto out;
file.c:			goto out;
file.c:		goto out;
file.c:		goto out;
file.c:		goto cpio;
file.c:	if(ccom() == 0)goto notc;
file.c:				goto out;
file.c:			if(i >= in)goto notc;
file.c:		if(ccom() == 0)goto notc;
file.c:		while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc;
file.c:		goto outa;
file.c:			goto notas;
file.c:			goto check; 
file.c:			if(nl++ > 6)goto notc;
file.c:		if(i >= in)goto notc;
file.c:			if(nl++ > 6)goto notc;
file.c:		if(i >= in)goto notc;
file.c:			if(nl++ > 6)goto notc;
file.c:		if(i >= in)goto notc;
file.c:	goto outa;
file.c:		while(buf[i++] != '\n')if(i >= in)goto notfort;
file.c:		goto outa;
file.c:	if(ascom() == 0)goto notas;
file.c:			goto outa;
file.c:			goto outa;
file.c:		if(ascom() == 0)goto notas;
file.c:			if(i >= in)goto notas;
file.c:		while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas;
file.c:				goto outa; 
file.c:				goto outa;
file.c:	goto outa;
file.c:			goto out;
file.c:			goto out;
file.c:		goto out; 
file.c:			goto out;
file.c:					goto out;
find.c:		goto usage;
find.c:		goto And;
find.c:		if(!EQ(a, ")")) goto err;
find.c:			goto cerror;
find.c:				if(c == EOF) goto RET;
find.c:					if(c == EOF) goto RET;
find.c:				goto RET;
find.c:				goto ret;
find.c:				goto ret;
find.c:				goto ret;
find.c:				goto ret;
find.c:	if (c==scc) goto caseq;
find.c:				goto again;
find.c:		goto again;
fsck.c:		goto retry;
fsck.c:				goto again;
fsplit.c:	if( compar(&s,"subroutine") )	goto bot;
fsplit.c:	else if( compar(&s,"function") )	goto bot;
fsplit.c:	else if( compar(&s,"procedure") )	goto bot;
fsplit.c:	else if( compar(&s,"program") )	goto bot;
fsplit.c:	else if( compar(&s,"real") )	goto loop;
fsplit.c:	else if( compar(&s,"integer") )	goto loop;
fsplit.c:	else if( compar(&s,"logical") )	goto loop;
fsplit.c:	else if( compar(&s,"double") )	goto loop;
fsplit.c:	else if( compar(&s,"precision") )	goto loop;
fsplit.c:	else if( compar(&s,"complex") )	goto loop;
fsplit.c:	else if( compar(&s,"character") ) goto loop;
fsplit.c:		goto loop;
fsplit.c:		goto bot;
grep.c:			goto out;
grep.c:			goto cerror;
grep.c:				goto defchar;
grep.c:				goto defchar;
grep.c:				goto cerror;
grep.c:					goto cerror;
grep.c:					goto cerror;
grep.c:					goto cerror;
grep.c:					goto cerror;
grep.c:				goto found;
grep.c:			goto nfound;
grep.c:					goto found;
grep.c:			goto nfound;
grep.c:				goto found;
grep.c:		goto star;
grep.c:		goto star;
grep.c:		goto star;
gsi.c:			goto loop;
gsi.c:	goto loop;
init.c:			goto loop;
init.c:		goto loop;
init.c:		goto loop;
init.c:		goto loop;
init.c:		goto loop;
init.c:		goto loop;
init.c:			goto contin1;
init.c:			goto contin1;
kill.c:				goto foundsig;
kill.c:			goto usage;
ld.c:			goto next;
ld.c:			goto next;
ld.c:			goto next;
ld.c:			goto next;
ld.c:		goto top;
ld.c:		goto top;
ld.c:	goto top;
ld.c:		goto top;
ld.c:		goto top;
ld.c:	goto top;
ln.c:		goto usage;
ln.c:			goto usage;
ln.c:			goto usage;
mkfs.c:		goto f3;
mkfs.c:		goto f2;
mkfs.c:		goto f1;
mkfs.c:		goto f1;
mkfs.c:		goto loop;
mkfs.c:		goto loop;
mknod.c:		goto usage;
mknod.c:		goto usage;
mknod.c:		goto usage;
mknod.c:		goto usage;
mkstr.c:			goto out;
ncheck.c:						goto pr;
news.c:			goto finish;
nm.c:			goto out;
number.c:			goto out;
number.c:			goto out;
od.c:					goto notsame;
reloc.c:			goto usage;
restor.c:			goto usage;
restor.c:			goto getvol;
restor.c:			goto newvol;
restor.c:			goto newvol;
restor.c:			goto newvol;
restor.c:			goto rbits;
restor.c:						goto newvol;
restor.c:				goto again;
restor.c:					goto done;
restor.c:		goto checkdone;
restor.c:				goto ragain;
restor.c:				goto ragain;
restor.c:				goto ragain;
restor.c:				goto ragain;
restor.c:			goto finish;
restor.c:	goto start;
restor.c:			goto eloop;
restor.c:					goto eloop;
restor.c:				goto loop;
restor.c:				goto loop;
restor.c:				goto loop;
restor.c:			goto found;
restor.c:		goto next;
rev.c:					goto eof;
sa.c:				goto yes;
sa.c:		goto gshm;
sa.c:					goto nextprobe;
seq.c:			goto out;
sort.c:			goto loop;
sort.c:				else goto ret;
sort.c:				else goto ret;
sort.c:				goto loop;
sort.c:					goto loop;
sort.c:			goto loop;
sort.c:			goto start;
spline.c:			goto again;
split.c:			goto cerror;
split.c:				goto defchar;
split.c:				goto defchar;
split.c:				goto cerror;
split.c:					goto cerror;
split.c:					goto cerror;
split.c:					goto cerror;
split.c:					goto cerror;
split.c:				goto found;
split.c:			goto nfound;
split.c:					goto found;
split.c:			goto nfound;
split.c:				goto found;
split.c:		goto star;
split.c:		goto star;
split.c:		goto star;
stty.c:				goto done1;
stty.c:				goto done1;
stty.c:					goto cont;
stty.c:				goto done1;
stty.c:				goto cont;
stty.c:				goto cont;
sum.c:					goto usage;
tabs.c:				goto done;
tail.c:		if(bylines!=-1) goto errcom;
tail.c:		if(bylines!=-1) goto errcom;
tail.c:		if(bylines!=-1) goto errcom;
tail.c:		goto errcom;
tail.c:		goto keep;
tail.c:			goto copy;
tail.c:				goto brka;
tail.c:						goto brkb;
tar.c:			goto gotit;
tar.c:				goto gotit;
tar.c:		goto loop;
tar.c:		goto loop;
tcat.c:		if(*bptr == '!'){callunix(&buf[1]); fputs("!\n", stderr); goto next;}
tcat.c:				goto next;
tcat.c:				goto next;
tcat.c:				goto next;
tcat.c:		goto a1;
touch.c:		goto create;
touch.c:	goto create;
touch.c:	goto bad;
touch.c:	goto bad;
touch.c:	goto bad;
touch.c:		goto bad;
tr.c:		goto again;
units.c:		goto loop;
units.c:		goto fp;
units.c:		goto loop1;
units.c:			goto conform;
units.c:		goto fp;
units.c:	goto loop;
units.c:		goto fp;
units.c:	goto loop;
units.c:	goto loop;
units.c:		goto loop;
units.c:	goto loop;
units.c:			goto l1;
units.c:			goto loop;
units.c:		goto loop;
units.c:		goto l0;
units.c:		goto l0;
units.c:			goto l0;
units.c:				goto redef;
units.c:			goto l0;
units.c:		goto redef;
units.c:		goto l0;
units.c:			goto l0;
units.c:				goto l0;
units.c:	goto l0;
units.c:	goto l0;
units.c:		goto l1;
units.c:		goto l1;
units.c:	goto l0;
xstr.c:				goto def;
xstr.c:				goto def;
xstr.c:				goto def;
xstr.c:			goto def;
xstr.c:			goto out;
xstr.c:					goto gotc;
xstr.c:				goto out;

1 Like

Based on the discussion across 161 posts, I have understood that I should avoid using too many goto statements in a program. This is because it's easy to make errors, such as writing goto L1B; instead of goto L1A;. Such mistakes can make debugging very difficult, contribute to creating "spaghetti code," and ultimately increase the downtime in program development.

A Comparative Study to Exhibit the Superiority of goto-free Program over goto-based Proram (Referring to Fig- Fig-1A and 1B)


LED-D2 will turn for 3 seconds when ATtiny85 sees HIGH at Dpin-2. It will go Off if 3-sec has elapsed or K1 is opened within that 3-sec window.

Figure-1A;


Figure-1B:

A: C Codes using goto statements; where incorrect label numbers could be entered/typed.

#define ledPin  1 // UNO 13
#define Button 2 //UNO 2
unsigned long int presentMillis;

void setup()
{
  pinMode(Button, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop()
{
L1:
  if (digitalRead(Button) == HIGH) //Button is closed
  {
L2: delay(100); //wait for bouncing period of Button
L3: if (digitalRead(Button) == HIGH) //Is Button still close
    {
L4:   digitalWrite(ledPin, HIGH);
      presentMillis = millis();
L5:   if (millis() - presentMillis >= 3000) //test interval
      {
L6:     digitalWrite(ledPin, LOW);
L7:     while (digitalRead(Button) == HIGH)
        {
          ; //wait until Button is opened
        }
        goto L1; //Button is Opened
      }
      else
      {
L8:     if (digitalRead(Button) == LOW)
        {
          goto L6; // Button is opened
        }
        else
        {
          goto L5;
        }
      }
    }
  }
}

B: C Codes without goto statements; where there is absolutely no chance of label reated mistakes.

#define ledPin  1 //UNO = 13
#define Button 2 //UNO = 2
unsigned long int presentMillis;

void setup()
{
  pinMode(Button, INPUT);
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  if (digitalRead(Button) == HIGH) //Button is closed L1:
  {
    delay(100); //wait for bouncing period of Button L2:
    if (digitalRead(Button) == HIGH) //Is Button still close L3:
    {
      digitalWrite(ledPin, HIGH); //L4:
      presentMillis = millis(); 
      while (millis() - presentMillis < 3000)  //test interval  L5:
      {
        if (digitalRead(Button) == LOW) //L8:
        {
          break;
        }
      }
      digitalWrite(ledPin, LOW);  //LED2 is turned Off L6:
      while (digitalRead(Button) == HIGH) //L7:
      {
        ; //wait
      }
    }
  }
}
1 Like

The whole discussion is that you should avoid it, period :slight_smile:


note that in your example there is no need to wait for the bouncing. you could trigger the LED HIGH as soon as you detect the front as you risk loosing a good 99ms press and at the end after the release you should also have your anti-bounce delay

1 Like

What about also getting rid of the break and if statements by using a compound condition in the containing while statement?

2 Likes

everything is possible :wink: I guess it's not the topic of this post though.

If that is done, the readability will increase at the cost of simplicity.

I keep seeing this topic pop up as a discussion so I keep thinking about it a bit like that pop melody you just can't get out of your head. So you're stuck with me, even though I'm no academic like many of you esteemed gurus. You know me: I just make Hallowe'en props.

But the way I see it, goto as I understand it makes it too easy to make easy shortcuts in programming and worse than that, too difficult for someone wiser or more experienced to correct as it seems too easy to break structure, whatever that's called.

What I mean is, since goto as I understand it, ignores everything else and bullies its way to wherever you want in program, it breaks "the progress of the process" or whatever that phrase was that Dijkstra kept repeating in that paper. goto is a cheat code in a video game with unpredictable results, before there were cheat codes or really even video games.

Quick example: I like to mod the video game Fallout 4. It's cool since Bethesda left the game basically open source and offered something called the Creation Kit for anyone at all to get to the engine level of the game and literally change anything they wanted to, skill provided. As it turns out, in this game that takes place in a post apocalyptic, desolate wasteland, and one of the things modders wanted to do was take out all the little bits of garbage and debris and make a beautiful world. So they went to taking out all the blasted trees and scorched rocks and such. goto a beautiful, clean landscape you might say.
One problem...to save memory space, all those things that modders just erased willy nilly weren't standalone objects - they were part of a larger object, embedded in something called the precombines. No problem immediately...but eventually you will corrupt the game and break your save file. So what? Well...
Another cool feature of Fallout 4 is the ability to rebuild new towns and such, like Minecraft if you're not familiar with Fallout 4. Fun right? So what happens when a player tries to place say, a nice healthy tree on top of the same coordinates where the clumsily erased blasted out tree used to be in the larger object in the precombines?
Crash to desktop.
I've seen it, I've done it. I know how to avoid it. Don't use mods that break precombines, which sound an awful lot to me like goto in the Creation Engine.
Seems to me like the real point of the paper by Dijkstra was to follow a predictable, in both the forward and backward dimension of time to avoid a coding practice where "Oh look, it's a squirrel!" is the key driver to the program's success.

1 Like

here's a usage from 8ed unix split.c

compile(astr)
char *astr;
{
	register c;
	register char *ep, *sp;
	char *cstart;
	char *lastep;
	char *bracketp;
	int cclcnt;
	int closed;
	char neg;

	expp=malloc(sizeof *expp);
	if(expp==NULL)
		errexit("split: too many expressions; can't malloc\n", (char *)NULL);
	if(firstexp==0) {
		firstexp=expp;
		lastexp=expp;
	} else {
		lastexp->next = expp;
		lastexp = expp;
	}
	expp->next=0;
	ep = expp->expbuf;
	sp = astr;
	lastep = 0;
	bracketp = bracket;
	closed = numbra = 0;
	if (*sp == '^') {
		circf++;
		sp++;
	}
	for (;;) {
		if (ep >= &expp->expbuf[ESIZE])
			goto cerror;
		if ((c = *sp++) != '*')
			lastep = ep;
		switch (c) {

		case '\0':
			*ep++ = CEOF;
			if(expp==firstexp)
				nbra=numbra;
			else if(nbra!=numbra)
				errexit("split: inconsistent parentheses in expression %s\n", astr);
			return;

		case '.':
			*ep++ = CDOT;
			continue;

		case '*':
			if (lastep==0 || *lastep==CBRA || *lastep==CKET)
				goto defchar;
			*lastep |= STAR;
			continue;

		case '$':
			if (*sp != '\0')
				goto defchar;
			*ep++ = CDOL;
			continue;

		case '[':
			if(&ep[17] >= &expp->expbuf[ESIZE])
				goto cerror;
			*ep++ = CCL;
			neg = 0;
			if((c = *sp++) == '^') {
				neg = 1;
				c = *sp++;
			}
			cstart = sp;
			do {
				if (c=='\0')
					goto cerror;
				if (c=='-' && sp>cstart && *sp!=']') {
					for (c = sp[-2]; c<*sp; c++)
						ep[c>>3] |= bittab[c&07];
					sp++;
				}
				ep[c>>3] |= bittab[c&07];
			} while((c = *sp++) != ']');
			if(neg) {
				for(cclcnt = 0; cclcnt < 16; cclcnt++)
					ep[cclcnt] ^= -1;
				ep[0] &= 0376;
			}

			ep += 16;

			continue;

		case '\\':
			if((c = *sp++) == '(') {
				if(numbra >= NBRA) {
					goto cerror;
				}
				*bracketp++ = numbra;
				*ep++ = CBRA;
				*ep++ = numbra++;
				continue;
			}
			if(c == ')') {
				if(bracketp <= bracket) {
					goto cerror;
				}
				*ep++ = CKET;
				*ep++ = *--bracketp;
				closed++;
				continue;
			}

			if(c >= '1' && c <= '9') {
				if((c -= '1') >= closed)
					goto cerror;
				*ep++ = CBACK;
				*ep++ = c;
				continue;
			}

		defchar:
		default:
			*ep++ = CCHR;
			*ep++ = c;
		}
	}
    cerror:
	errexit("split: RE error\n", (char *)NULL);
}

My question to @Delta_G is: does that alternative always exit? When we look into post #169 @gcjr, it is observed that goto has been used to make an exit from a deep down point of the program.

I am again urged to devise a short program which will clearly demonstrate that a goto is absolutely necessay to make an exit.

It’s never the case. There are always alternative, I have an example in an earlier post but it involves cascade of testing a flag to go up one level at a time in the nested elements. That’s less efficient than a goto (memory used for the flag(s) and cpu cycles + program memory needed for tests).

The example given for split does not show such deep nesting so it was a programmer’s choice. There were possible alternatives but it was probably a pragmatic way of dealing with the need.

1 Like

Don’t forget to ‘flush’.

@GolamMostafa

Note how the function in post #169 starts

compile(astr)
char *astr;
{

I think that that indicates how old that code is. No parameter types in the parenthesis (they are after that) and no return type. Even K&R 2nd edition book does not seem to use that construction.

Some more points:

  1. I agree with @Delta_G that a decision regarding the goto was taken long ago and I think that it is not representative for the current state of affairs. And @J-M-L demonstrated the alternative earlier on.
  2. There is a difference between teaching beginning C/C++ programmers the use of goto for starters or teaching it at a later stage as an emergency measure. From K&R
    screenshot
1 Like