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?
CodePudding user response:
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();
}
CodePudding user response:
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.