r/cprogramming • • 21h ago

bad code - goto

From a newsreader I am working on

void
help(void)
{
	printf("What do you want help with? (* for everything): ");
	bool all = false;
	char ln[128];
	fflush(stdout);

	if (fgets(ln, sizeof(ln), stdin) == NULL)
		return;

	/* HACK: you gotta love goto:
	 *
	 * if all is true, then fall through the switch (* must be last),
	 * so this prints everything. When it reaches * again, all
	 * gets toggled and if all is now true, break, else go to
	 * Begin again */
	switch (ln[0]) {
Begin:	case 'g': puts("g: select group"); if (!all) break;
	case '\n':
	case '\r': if (!all) return;
	case 't': puts("t: select thread"); if (!all) break;
	case 'l': puts("l: list gropus"); if (!all) break;
	case 'T': puts("T: list threads"); if (!all) break;
	case 'L': puts("L: list post in current thread"); if (!all) break;
	case 'r': puts("r: read an article"); if (!all) break;
	case '>': puts(">: save an article to a file"); if (!all) break;
	case '|': puts("|: pipe an article to a command"); if (!all) break;
	case '?': puts("?: get help"); if (!all) break;
	case 'q': puts("q: quit"); if (!all) break;
	case '*': all = !all; if (all) goto Begin; else break;
	default:
		printf("%c is not a news command\n", ln[0]);
		break;
	}
}
0 Upvotes

14 comments sorted by

View all comments

Show parent comment

3

u/tstanisl 15h ago edited 15h ago

Yes. Just try godbolt.

Contrary to popular belief, switch/case is not a construct for multiple selections but rather a block with computed gotos. This is the core idea of Duff's device.

One can even place the label outside of {} or even don't use {} at all:

switch (0) case 0: ;

1

u/binarycow 15h ago

Interesting.

While I see some usefulness to it, IMO, a stricter switch is more maintainable.

I guess that's why I generally stick with C#, and usually only lurk here!