Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing arguments to functions with const parameters: is it faster?

Tags:

Consider, for example:

int sum(int a, int b) {     return a + b; } 

vs.

int sum(const int a, const int b) {     return a + b; } 

Is the second approach in general faster?

Function parameters in C are copied and sent to the function, so that changes inside the function do not affect the original values. My reasoning is that in the second sum above, the compiler knows for sure that a and b are not modified inside the function, so it can just pass the original values without copying them first. That's why I think the second sum is faster than the first. But I don't really know. In the particular simple example of sum above, the differences, if any, should be minimal.

Edit: The sum example is just to illustrate my point. I don't expect that in this particular example there should be large differences. But I wonder if in more complicated situations the const modifier inside a function parameter can be exploited by the compiler to make the function faster. I doubt that the compiler can always determine whether a parameter is changed inside a function (hence my 2nd question below); hence I'd expect that when it finds a const modifier, it does something different than when there's no const modifier.

Question: In general, a function will be faster when its arguments are const, than when they are not?

Question 2: In general, can a C compiler (theoretically) always determine whether a function parameter is changed inside the function?

like image 919
becko Avatar asked Sep 06 '12 00:09

becko


People also ask

Why might it be good for a function parameter to be const?

If your function does not modify the data pointed to by a pointer parameter, declare the function parameter as const. That way the compiler will verify that your function indeed does not change the data. It will also allow a pointer to a constant to be passed to the function without issuing an error message.

Why would we put the const keyword in front of a pass by reference parameter?

The const keyword in front of the object name is used to guarantee that your function does not modify the objects that are passed to the function by reference or pointer. Not only will this tell other programmers that your function is safe to use, it is also strictly enforced by the compiler.

Under what circumstances should you declare a function as const?

A function becomes const when the const keyword is used in the function's declaration. The idea of const functions is not to allow them to modify the object on which they are called. It is recommended the practice to make as many functions const as possible so that accidental changes to objects are avoided.

Is it better to pass by reference?

2) For passing large sized arguments: If an argument is large, passing by reference (or pointer) is more efficient because only an address is really passed, not the entire object.


2 Answers

Short answer: No

Long answer, no, with proof.

I ran this test, a couple of times, and saw no real time difference, on my MacBook pro compiled with clang:

int add(int a, int b) {     return a + b; }  const int cadd(const int a, const int b) {     return a + b; }  int main (int argc, char * argv[]) { #define ITERS 1000000000      clock_t start = clock();     int j = 0;     for (int i = 0; i < ITERS; i++)     {         j += add(i, i + 1);     }      printf("add took %li ticks\n", clock() - start);      start = clock();     j = 0;     for (int i = 0; i < ITERS; i++)     {         j += cadd(i, i + 1);     }      printf("cadd took %li ticks\n", clock() - start);      return 0; } 

Output

 add took 4875711 ticks cadd took 4885519 ticks 

These times really should be taken with a grain of salt, however, as clock isn't the most accurate of timing functions, and can be influenced by other running programs.

So, here is the compared assembly generated:

_add:     .cfi_startproc     pushq   %rbp     .cfi_def_cfa_offset 16     .cfi_offset %rbp, -16     movq    %rsp, %rbp     .cfi_def_cfa_register %rbp     movl    %edi, -4(%rbp)     movl    %esi, -8(%rbp)     movl    -4(%rbp), %esi     addl    -8(%rbp), %esi     movl    %esi, %eax     popq    %rbp     ret  _cadd:                                      .cfi_startproc         pushq   %rbp     .cfi_def_cfa_offset 16     .cfi_offset %rbp, -16     movq    %rsp, %rbp     .cfi_def_cfa_register %rbp     movl    %edi, -4(%rbp)     movl    %esi, -8(%rbp)     movl    -4(%rbp), %esi     addl    -8(%rbp), %esi     movl    %esi, %eax     popq    %rb 

So, as you can see, there is No difference between the two. Passing an argument as const is only a hint to the caller the the argument will not be changed, and in a simple scenario like the one described above, will not result in any different assembly compiled.

like image 137
Richard J. Ross III Avatar answered Nov 03 '22 02:11

Richard J. Ross III


The answer probably depends on your compiler, the optimization level, and whether the compiler decides to inline the function. If you are curious about these things, it is easy to just look at the actual assembly produced by your compiler and find out.

like image 32
David Grayson Avatar answered Nov 03 '22 02:11

David Grayson