problems/risks due to programming language, stories requ

Richard O'keefe ok at goanna.oz.au
Fri Mar 16 12:47:39 AEST 1990


In article <1306 at mindlink.UUCP>, a563 at mindlink.UUCP (Dave Kirsch) writes:
> Do this in Pascal:
> switch (i) {
>   case 2 :  /* Add 2 to j */
>     j++;
>   case 1 :  /* Add 1 to j */
>     j++;
>   case 0 :  /* Print j out */
>     printf("%d\n", j);
>     break;
>   default :
>     printf("Illegal value in switch.\n");
>     abort();
> }

Just for grins, I'll do it in C:
	if (i < 0 || i > 2) {
	    printf("Illegal value %d in switch.\n", i);
	    abort();
	}
	j += i;
	printf("%d\n", j);

More seriously, I have often run into the "this case is just like that
only a bit different" problem several times.  Trouble is, that with more
than one minor variant, it is hard to make them all fall through.  It
can even be worth nesting your switches:
	switch (i) {
	    case 1: case 2: case 3:
		switch (i) {
		    case 1: ... ; break;
		    case 2: ... ; break;
		    case 3: ... ; break;
		}
		/* stuff common to cases 1, 2, and 3 */
		break;
	    ... and so on ...
	}
If the cost of the extra switch() is a significant part of the cost
of your program, you have an amazingly cheap program.  The reason that
I sometimes use this approach is that generally I don't *quite* want a
fall-through exactly.  Suppose I want
	case 1: i++; COMMON PART
	case 2: j++; COMMON PART
To exploit fall-through here, I would have to use
	case 1: j--; i++;
	case 2: j++; COMMON PART
which is *really* ugly and unmaintainable.

The one case where I do regularly use fall-through without any trace
of guilt is when "unwinding" side effects.  E.g.

    {
	int state = 0;

	f = fopen(...);
	if (!f) goto ERROR;
	state = 1;
	p = malloc(...);
	if (!p) goto ERROR;
	state = 2;
	...
	return OK_STATUS;
ERROR:	switch (state) {
	    case 2: free(p);
	    case 1: fclose(f);
	    case 0: break;
	}
	return ERROR_CODE;
    }



More information about the Comp.lang.c mailing list