Some time ago I noticed that a certain programming construct I like to use in my C programs is quite unique to my programming style and that it seams like noone else is using it.. So I decided to write this little article about it and give it a name: Clifford's Device
The name Clifford's Device was choosen in the style of Duff's Device.
What is it?
A Clifford's Device is a coding trick in C and simmilar languages. A Clifford's Device is a section of code is surrounded by if (0) { label: … } so it is skipped in the normal flow of execution and is only reached via the goto label, reintegrating with the normal flow of execution and the end of the if (0) statement. It solves a situation where one would usually need to duplicate code or create a state variable holding the information if the additional code block should be called.
Here is a little example:
#include <stdio.h>
int main(int argc, char **argv)
{
int num;
if (argc != 3) {
fprintf(stderr, "Usage: %s {BIN|OCT|DEC|HEX|STR} {ARG}\n", argv[0]);
return 1;
}
if (!strcmp(argv[1], "BIN")) {
num = strtol(argv[2], NULL, 2);
goto number_mode;
} else
if (!strcmp(argv[1], "OCT")) {
num = strtol(argv[2], NULL, 8);
goto number_mode;
} else
if (!strcmp(argv[1], "DEC")) {
num = strtol(argv[2], NULL, 10);
goto number_mode;
} else
if (!strcmp(argv[1], "HEX")) {
num = strtol(argv[2], NULL, 16);
goto number_mode;
} else
if (!strcmp(argv[1], "STR")) {
printf("Called with string argument: '%s'\n", argv[2]);
} else {
printf("Called unsupported mode: '%s'\n", argv[1]);
}
/* Clifford's Device */
if (0) {
number_mode:
printf("Called with numeric argument: %d\n", num);
}
return 0;
}
But aren't gotos evil?
In my opinion only if you use them in a way which makes your code harder to read. But sure: this is always a matter of tase.. 😉
Read also on this topic: Structured Programming with Goto Statements (Computing Surveys 6:4, 1974) from Donald E. Knuth.
Is this a performance optimization?
No, not really. You can simply copy the same code to all the places where you need it and most modern optimizing compilers will detect this and generate the same code as if you would have used Clifford's Device instead. However, this may make your program harder to maintain and read. The examples here have only one line of code in the if (0) { … } block. But in real-world applications it my be dozens lines of code.
Clifford's Device and switch statements
A switch statement is nothing else than a computed goto statement. So it is possible to use Clifford's Device with a switch statement as well:
#include <stdio.h>
int main(int argc)
{
char *num;
switch (argc-1)
{
if (0) { case 0: num = "zero"; }
if (0) { case 2: num = "two"; }
if (0) { case 3: num = "three"; }
if (0) { case 4: num = "four"; }
if (0) { case 5: num = "five"; }
if (0) { default: num = "many"; }
printf("Called with %s arguments.\n", num);
break;
case 1:
printf("Called with one argument.\n");
}
return 0;
}