I have this piece of code for testing the behaviour of switch statement versus function pointers:
#include <stdio.h>
#include <time.h>
int mySum(int startingValue)
{
return startingValue += 1;
}
int mySub(int startingValue)
{
return startingValue -= 1;
}
int main()
{
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("USING SWITCH\n");
printf("Start time: %s", asctime(timeinfo));
int startingValue = 25;
int currentOperation = 0;
// Using switch
for (long long i = 0; i < 10000000000; i++)
{
switch (currentOperation)
{
case 1:
startingValue = mySum(startingValue);
break;
case 0:
startingValue = mySub(startingValue);
break;
}
if (currentOperation)
currentOperation = 0;
else
currentOperation = 1;
}
printf("Result is: %d\n", startingValue);
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("End time: %s", asctime(timeinfo));
printf("\n\n\n");
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("USING FUNCTION POINTERS\n");
printf("Start time: %s", asctime(timeinfo));
startingValue = 25;
currentOperation = 0;
// Using function pointers
int (*mySwitchOfFunctionPointers[2])(int x);
mySwitchOfFunctionPointers[0] = &mySub;
mySwitchOfFunctionPointers[1] = &mySum;
for (long long i = 0; i < 10000000000; i++)
{
startingValue = (*mySwitchOfFunctionPointers[currentOperation])(startingValue);
if (currentOperation)
currentOperation = 0;
else
currentOperation = 1;
}
printf("Result is: %d\n", startingValue);
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("End time: %s", asctime(timeinfo));
return 0;
}
The output is this so code executes instantly with switch statement but it needs many seconds with function pointers:
USING SWITCH
Start time: Mon Oct 25 18:04:06 2021
Result is: 25
End time: Mon Oct 25 18:04:06 2021
USING FUNCTION POINTERS
Start time: Mon Oct 25 18:04:06 2021
Result is: 25
End time: Mon Oct 25 18:04:34 2021
Compiled with
gcc -c main.c -o test.o -O3 -Wall -Wno-unused -std=c99
gcc test.o -o test
Why the second approach is slower than the first??? Is there something wrong in the code? Any idea?
The compiler can inline the switch and then the optimizer is smart enough to realize that your entire loop is a no-op so optimizes it out. It does not do this with the function pointers. See https://godbolt.org/z/qxxoof5cn
If you change your code to something that the compiler cannot optimize out so trivially you will get very different results. For example:
int mySum(int startingValue)
{
return startingValue += rand();
}
int mySub(int startingValue)
{
return startingValue -= rand();
}
The compiler optimization argument (-O3) is responsible for this behaviour.
The compiler can optimize the first for-Loop with the switch inside, because it has every needed information about this code.
Unfortunately the compiler can't optimize code with function-pointers. Since the compiler do not know what functions are called.
If you delete the -O3 argument at compiling, you will see that, function pointers and the switch-case statements need similar times.