which would be faster? I do not mean compile time.
which would be faster? I do not mean compile time.
Measure with typical input and find out.
Then measure it on a different compiler, and then wonder why the answer might be different.
Some things to consider:
Are the cases compact (like 1,2,3,4) or sparse (1,100,10000,1000000)?
Are case frequencies random or biased in favour of certain values?
If the switch fits, you must commit.
It's hard to imagine a switch being slower than nested ifs and easy to imagine it being faster. A particularly smart compiler might transform your if into roughly the same code as the switch but if your situation fits the constraints of a switch then you should give the compiler the hint by coding it that way.
I just made a little program to generate two programs, one using if/else if's and the other using a switch. You then run the two programs for the same number of reps (and with the same random seed) to compare the results. Of course, this is just for a particular system with this particular (random) data, but for me the switch blows the if/else if's out of the water.
The files generated look like this (the above program was passed a command line value of 10 to generate 10 "statements").Code:#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUMSTATEMENTS 100 // default number of statements
#define RANDLIMIT 100000
#define DEFAULTREPS 10000
#define TAB " " // 8 spaces
void head(FILE *f);
void tail(FILE *f);
int *nums;
int inums = 0;
int in_nums(int n) {
for (int i = 0; i < inums; i++)
if (nums[i] == n)
return 1;
return 0;
}
int rnd() { // no repeats
int r;
do r = rand() % RANDLIMIT; while (in_nums(r));
nums[inums++] = r;
return r;
}
int main(int argc, char **argv) {
int num_statements = argc > 1 ? atoi(argv[1]) : NUMSTATEMENTS;
nums = malloc(num_statements * 2 * sizeof *nums);
srand(time(NULL));
FILE *f_if = fopen("if.c", "w");
if (!f_if) return 1;
FILE *f_switch = fopen("switch.c", "w");
if (!f_switch) return 1;
head(f_if);
head(f_switch);
int a = rnd(), x = rnd();
fprintf(f_if, TAB "if (a == %d) x = %d;\n", a, x);
fprintf(f_switch, TAB "switch (a) {\n");
fprintf(f_switch, TAB "case %d: x = %d; break;\n", a, x);
for (int i = 1; i < num_statements; i++) {
a = rnd();
x = rnd();
fprintf(f_if, TAB "else if (a == %d) x = %d;\n", a, x);
fprintf(f_switch, TAB "case %d: x = %d; break;\n", a, x);
}
x = rnd();
fprintf(f_if, TAB "else x = %d;\n", x);
fprintf(f_switch, TAB "default: x = %d;\n", x);
fprintf(f_switch, TAB "}\n");
tail(f_if);
tail(f_switch);
fclose(f_if);
fclose(f_switch);
return 0;
}
void head(FILE *f) {
fprintf(f,
"#include <stdio.h>\n"
"#include <stdlib.h>\n"
"#include <time.h>\n"
"\n"
"#define DEFAULTREPS %d\n"
"#define RANDLIMIT %d\n"
"\n"
"int main(int argc, char **argv) {\n"
" int reps = argc > 1 ? atoi(argv[1]) : DEFAULTREPS;\n"
" srand(argc > 2 ? atoi(argv[2]) : time(NULL));\n"
"\n"
" int a, x, sum = 0;\n"
" clock_t t0 = clock();\n"
" for (int i = 0; i < reps; i++) {\n"
" a = rand() %% RANDLIMIT;\n",
DEFAULTREPS, RANDLIMIT);
}
void tail(FILE *f) {
fprintf(f,
" sum += x;\n"
" }\n"
"\n"
" clock_t t1 = clock();\n"
" printf(\"%%.3f ms\\n\", (double)(t1 - t0) / CLOCKS_PER_SEC * 1000);\n"
" printf(\"%%d\\n\", sum); // meaningless!\n"
" return 0;\n"
"}\n");
}
Of course, much bigger test programs should be used (1000+ statements).Code:// if.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DEFAULTREPS 10000
#define RANDLIMIT 100000
int main(int argc, char **argv) {
int reps = argc > 1 ? atoi(argv[1]) : DEFAULTREPS;
srand(argc > 2 ? atoi(argv[2]) : time(NULL));
int a, x, sum = 0;
clock_t t0 = clock();
for (int i = 0; i < reps; i++) {
a = rand() % RANDLIMIT;
if (a == 41589) x = 45672;
else if (a == 68120) x = 53568;
else if (a == 22379) x = 55723;
else if (a == 28291) x = 47980;
else if (a == 92190) x = 66782;
else if (a == 15707) x = 4730;
else if (a == 90340) x = 65562;
else if (a == 3880) x = 795;
else if (a == 30637) x = 91858;
else if (a == 27698) x = 15741;
else x = 70790;
sum += x;
}
clock_t t1 = clock();
printf("%.3f ms\n", (double)(t1 - t0) / CLOCKS_PER_SEC * 1000);
printf("%d\n", sum); // meaningless!
return 0;
}
// switch.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DEFAULTREPS 10000
#define RANDLIMIT 100000
int main(int argc, char **argv) {
int reps = argc > 1 ? atoi(argv[1]) : DEFAULTREPS;
srand(argc > 2 ? atoi(argv[2]) : time(NULL));
int a, x, sum = 0;
clock_t t0 = clock();
for (int i = 0; i < reps; i++) {
a = rand() % RANDLIMIT;
switch (a) {
case 41589: x = 45672; break;
case 68120: x = 53568; break;
case 22379: x = 55723; break;
case 28291: x = 47980; break;
case 92190: x = 66782; break;
case 15707: x = 4730; break;
case 90340: x = 65562; break;
case 3880: x = 795; break;
case 30637: x = 91858; break;
case 27698: x = 15741; break;
default: x = 70790;
}
sum += x;
}
clock_t t1 = clock();
printf("%.3f ms\n", (double)(t1 - t0) / CLOCKS_PER_SEC * 1000);
printf("%d\n", sum); // meaningless!
return 0;
}
To run the generated files pass them the number of reps and a random seed (the same values to each program).