0

Problem Description

I have a function which takes in a const pointer to a const double array on which I loop over using the size as boundary check inside my_func.

Declaration in .h

void my_func(const double * const my_array, size_t size);

Implementation in .c

void my_func(const double * const my_array, size_t size) {
  for (size_t idx = 0; idx < size; idx++) {
    do_something_with(my_array[idx]);
  }
}

I don't want the pointer to be changed inside the function hence making it * const. I don't want the data it is pointing to to be changed, hence the const double.

Clang-Tidy however wants me to have the function declaration drop the const on the pointer, making it

void my_func(const double * my_array, size_t size);

Clang-Tidy: Parameter 'my_array' is const-qualified in the function declaration; const-qualification of parameters only has an effect in function definitions

If I follow that advice but want to keep my constraints from above, my function declaration and definition are not the same anymore.

Questions

1)
Suppose my pointer argument is not const (const double * pointer_arg), if I change pointer_arg inside the function to point to another const double, is will the change be visible outside of my function? That is, after the line I executed my function, where fill pointer_arg point to? If it is not visible, does that mean the pointer is copied in by value? Is this even possible?

2)
What is the reason behind the decision that const in the declaration has no effect?

3)
What might be a benefit of having a different function signature in the declaration and definition? For me looking at my header file it is not clear how the implementation works, will it be const inside the function, won't it be? It raises confusion for me or a collaborator on the code.

4)
Should I drop the const in the declaration? What are best practices in this case?

Matt
  • 435
  • 4
  • 17
  • Little nitpicking: _"a function which takes in a const pointer to a const double **array**"_ -> [A pointer is not an array](https://stackoverflow.com/a/4810668/1753435)! – andreee Apr 10 '19 at 13:28

2 Answers2

6

1) Suppose my pointer argument is not const (const double * pointer_arg), if I change pointer_arg inside the function to point to another const double, is will the change be visible outside of my function?

No, it is not visible.

That is, after the line I executed my function, where fill pointer_arg point to?

Same as before.

If it is not visible, does that mean the pointer is copied in by value? Is this even possible?

That's exactly it.

2) What is the reason behind the decision that const in the declaration has no effect?

Because it is transferred by value, const has no effect (on the caller).

3) What might be a benefit of having a different function signature in the declaration and definition?

None. It actually should not even compile in C++.

4) Should I drop the const in the declaration? What are best practices in this case?

Yes, you should drop the const, because it doesn't help much. You're only prohibiting that the function changes its copy of the pointer, which is of no concern to the caller.

srdjan.veljkovic
  • 2,468
  • 16
  • 24
  • Thanks for the clarifications! I have a follow up question: If the pointer is copied by reference, is there a way to pass a pointer by reference and what would the consequences be? Is this done and is it dangerous if it is done? – Matt Apr 10 '19 at 13:26
  • 1
    In C, you can't pass by reference. In C++, you can, and the consequence is that any change in the function will be "seen" by the caller. It's done if you want an "(in-)out" parameter, though a return value is, in general, preferred. It's only dangerous if you make a mess. :) – srdjan.veljkovic Apr 10 '19 at 13:30
  • What should he do to force that the array elements cannot be changed in the function? – Paul Ogilvie Apr 10 '19 at 13:35
  • 2
    The declaration `void my_func(double const* my_array, size_t size);` will not allow the function to change the elements of `my_array` (what `my_array` points _to_). Function might change `my_array` pointer itself, but it has no reason to. – srdjan.veljkovic Apr 10 '19 at 13:51
1

The const attribute on the right of the * only affects the pointer itself, not the memory pointed to, the pointer itself is stored as an automatic variable.

void my_func(const double * my_array, size_t size);

Is the same as

void my_func(const double * const my_array, size_t size);

The const only affects the implementation, where my_array is used. my_array has automatic storage duration and cannot be changed in the implementation, when const is applied to it.

Given prototype:

int add(int a, int b);
// same as
int add(int const a, int const b);

Useful usage, force to keep the parameters a & b constant inside the function:

int add(int const a, int const b) {
    // a = a*b; // error
    return a+b;
};
cmdLP
  • 1,658
  • 9
  • 19