Here is the case,
I've tried to investigate a little bit advantages/disadvantages of implementation functions as follows :
void foo(const int a, const int b)
{
...
}
with common function prototype which is used as API and it's included in header file as shown below :
void foo(int a, int b)
I've found quite a huge discussion about this topic in the following question:
Similar Q
I agree there with answer from the rlerallut who is saying about self-documenting code and about being a little bit paranoid on the angle of security of your code.
However and this is the question, someone wrote there that using const
for the usual parameters passed to the function can bring some optimization benefits. My question is does anybody have real life example which proves this claim ?
"it might help the compiler optimize things a bit (though it's a long shot)."
I cant see how it would make a difference. It is most useful in this case to generate compiler warnings/errors when you try to modify the const variable...
If you were to try to invent an experiment to compare a function parameter declared as const or not for the purpose of optimization, pass by value. That means that this experiment would not modify the variable(s) because when const is used you would expect a warning/error. An optimizer that might be able to care, would already know that the variable is not modified in the code with or without the declaration and can then act accordingly. How would that declaration matter? If I found such a thing I would file the difference as a bug to the compiler bugboard.
For example here is a missed opportunity I found when playing with const vs not.
Note const or not doesnt matter...
void fun0x ( int a, int b);
void fun1x ( const int a, const int b);
int fun0 ( int a, int b )
{
fun0x(a,b);
return(a+b);
}
int fun1 ( const int a, const int b )
{
fun1x(a,b);
return(a+b);
}
gcc produced with a -O2 and -O3 (and -O1?)
00000000 <fun0>:
0: e92d4038 push {r3, r4, r5, lr}
4: e1a05000 mov r5, r0
8: e1a04001 mov r4, r1
c: ebfffffe bl 0 <fun0x>
10: e0850004 add r0, r5, r4
14: e8bd4038 pop {r3, r4, r5, lr}
18: e12fff1e bx lr
0000001c <fun1>:
1c: e92d4038 push {r3, r4, r5, lr}
20: e1a05000 mov r5, r0
24: e1a04001 mov r4, r1
28: ebfffffe bl 0 <fun1x>
2c: e0850004 add r0, r5, r4
30: e8bd4038 pop {r3, r4, r5, lr}
34: e12fff1e bx lr
Where this would have worked with less cycles...
push {r4,lr}
add r4,r0,r1
bl fun1x
mov r0,r4
pop {r4,lr}
bx lr
clang/llvm did the same thing the add after the function call burning extra stack locations.
Googling showed mostly discussions about const by reference rather than const by value and then the nuances of C and C++ as to what will or wont or can or cant change with the const declaration, etc.
If you use the const on a global variable then it can leave that item in .text and not have it in .data (and for your STM32 microcontroller not have to copy it from flash to ram). But that doesnt fit into your rules. the optimizer may not care and may not actually reach out to that variables home it might know to encode it directly into the instruction as an immediate based on the instruction set, etc...All things held equal though a non-const would have that same benefit if not declared volatile...
Following your rules the const saves on some human error, if you try to put that const variable on the left side of an equals sign the compiler will let you know.
I would consider it a violation of your rules, but if inside the function where it was pass by value you then did some pass by reference things and played the pass by reference const vs not optimization game....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With