1

Is there any reasn to use "void fun(void *const ptr)"? Or 'ptr' is always copy? Or it might help to optymise compiled code? Currently I can only see that it prevent from any pointers arithmetic as a ptr ir read-only. (void can be replaced by ony other type)

void fun(void * const param);
vs
void fun(void * param);
Dobijasek
  • 91
  • 1
  • 5
  • The `const` applies to the function context so it does not alter the pointer. (The `const` is not part of the signature.) It has no effect on the caller. – Eljay May 27 '22 at 13:06
  • The first option will disallow assigning to `param`, or otherwise modifying it. – Thomas Jager May 27 '22 at 13:09
  • C and C++ are distinct languages. Please choose only one of them for your question. Pointer arithmetic on a `void*` is not allowed in either of the two languages, anyway, and may be supported only as a non-standard extension of the compiler. – user17732522 May 27 '22 at 13:10
  • @ThomasJager But the pointer *only* – note the difference between `void const*` and `void* const`. – Aconcagua May 27 '22 at 13:11
  • `const` in this scenario doesn't change the signature, but when implementing the function there may reason to add this `const` to prevent the a different address from being assigned to the parameter... – fabian May 27 '22 at 13:13
  • @Aconcagua Yes, to the pointer only, that's what `param` is. – Thomas Jager May 27 '22 at 13:14
  • 1
    A common source of confusion. The first form is allowed but pointless in a *declaration* (without the body), e.g. in a header file. As Eljay says correctly, it does not change the function signature, and code analysis tools will remark on it. In a function *definition*, when the body is present, it *has* effect, the same it has on any other variable declaration: It declares the variable constant, preventing modification or assignment to it. The resulting situation is that you should have form 2 in a header and form 1 in the implementation, indicating that you don't want to modify `param`. – Peter - Reinstate Monica May 27 '22 at 13:15
  • It's actually the same if you make an ordinary `int` parameter const. There are some favouring having all parameters const *by principle* – I personally don't see any value in, though, just would lead to having to copy the value into yet another local variable *if* it should be modified. This has even more relevance in C++ as there might be significant overhead for (instead of just copying some memory that actually might even be optimised away by compiler in C). – Aconcagua May 27 '22 at 13:15
  • @Aconcagua The *by principle* idea is that the compiler will then detect accidental modification and if it turns out the modification is intentional you can remove the `const` rather than copy the value to another variable. The other way around the compiler will never give you a gold star for not modifying a variable not marked const. The *principle* is to use the qualifier that give you feedback from the compiler so you notice mistakes. – Goswin von Brederlow May 27 '22 at 13:41
  • what a wonderful moderation, marking consideration of "type * cont var" as a clone of "cont type var" consideration. I know meaning of 'const' at any place, I asked about practical POV using this kind construction. – Dobijasek May 27 '22 at 13:44
  • @GoswinvonBrederlow Well, placing it by principle *initially* and later removing it I can live with, but have encountered some refusing to remove even *then* ;) – Aconcagua May 27 '22 at 14:04
  • @Aconcagua Seems stupid for anything passed by value as it's already a copy of the original object. Maybe they are afraid they will change the type to something else in the future and forget to add const back in then. – Goswin von Brederlow May 27 '22 at 14:10
  • @GoswinvonBrederlow As consider I. The other case – accepted, as mentioned, though not really convinced of myself – if you need to fear to lose overview of where or when you modify a variable or not the function likely is to big anyway... – Aconcagua May 27 '22 at 14:17
  • @Aconcagua It's easy to mess up when you call other functions and they in turn call other functions and so on. The function may have a const and non-const overload and you don't even realize the wrong one gets called. – Goswin von Brederlow May 27 '22 at 15:02
  • @GoswinvonBrederlow Well, the overload problem doesn't get solved with having const parameters as default – could just as well be that the one with mutable parameter is the right one to be called. You wouldn't notice either... – Aconcagua Jun 01 '22 at 21:26
  • @Aconcagua I the non-const needs to be called but the parameters are const the compiler will fail and you can fix it. The other way around it will compile but just not do what you wanted. – Goswin von Brederlow Jun 01 '22 at 22:01
  • @GoswinvonBrederlow No, it won't fail – following your example there's still the const overload that shouldn't have get called in that case ;) – actually we don't even need overloads, if the parameter is accepted *by value* then it doesn't matter at all if the variable has been const or not, it will simply be copied... – Aconcagua Jun 02 '22 at 08:36
  • Just to clarify: I'm actually not arguing *against* having const by-value parameters, just showing up that the use of is much more limited than it might appear... Thus the whole matter renders oppinion-based anyway (once more...) – I *personally* am rather on the side of this being clutter (see [hyde's answer](https://stackoverflow.com/a/72406008/1312382)), so I don't apply this practice (unless required by coding conventions of the project), but again that's my *personal* choice... – Aconcagua Jun 02 '22 at 08:53

3 Answers3

1

Constness of an object (i.e. non-reference) parameter matters, and it doesn't matter depending on context. Both examples declare the same function, so in that regard constness of a parameter is ignored.

This applies to pointers and non-pointers equally. These sets declare exactly one function each:

void foo(int);
void foo(int const); // const normally applies to left
void foo(const int); // const is first token of type, so it applies to right

void bar(T*);
void bar(T* const);

void baz(T const *);
void baz(T const * const);
void baz(const T *);
void baz(const T * const);

Note that T const * is not a const qualified T *. It is a non-const qualified type; a non-const pointer to const T.

But if you declare the parameter as const in the function definition, then you cannot modify the parameter. So, in this case constness matters. Whether the parameter is modified or not doesn't matter to the caller because the parameter is a copy of the argument that the caller has no way to access. Example:

void foo(int x) {
    x++; // OK

void foo(int const) {
    x++; // Not OK

Or 'ptr' is always copy?

Yes. An object (i.e. non-reference) parameter is always a copy. In some cases that copy may be elided by the optimiser when that's more efficient.

Or it might help to optymise compiled code?

Quite unlikely.

Currently I can only see that it prevent from any pointers arithmetic

Constness won't prevent pointer arithmetic. Example:

void fun(T* const param) {
    T* next = param + 1;

Being void* does prevent pointer arithmetic unless you convert to another pointer type.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Re "Constness of an object parameter matters": Are you saying that for a class T there is a difference in the signature for `f(T);` and `f(const T);`? – Peter - Reinstate Monica May 27 '22 at 13:18
  • @Peter-ReinstateMonica I'm saying that there is a difference and there isn't a difference. Both of those declare the same function, but if you use `f(const T t)` in the definition, then you may not modify the parameter (such as `t.foo = 42;`). I'm specifying "object" because references (which are not objects) cannot be const qualified (which is different from being a reference to const). – eerorika May 27 '22 at 13:20
  • I see. I find the wording less than clear. – Peter - Reinstate Monica May 27 '22 at 13:50
  • *'then you may not modify the parameter (such as t.foo = 42;)'* – worth to mention that it *can* be modified *if* `foo` has been declared `mutable` within T or is that a too rarely applied exception? – Aconcagua Jun 02 '22 at 08:58
  • @Aconcagua I'm not sure if it's worth a mention :) but that's correct. – eerorika Jun 02 '22 at 09:00
0
void fun(void * const param);

Parameters in C are essentially same as local variable, just initialized by caller. Making a parameter (or a local non-static variable for that matter) const prevents the programmer from accidentally writing code which changes what this "local variable" points to.

But in practice this isn't something programmers have problems with, it's not a source of subtle bugs, so it doesn't add much value in practice. Also compiler is smart enough to know you don't change local variable if you simply don't write code doing so, so it doesn't enable any extra optimizations, either.

Verdict: adding that const is useless clutter, don't do it. But this is just opinion, someone may disagree for a number of reasons.


Note: Not to be confused with pointer to const, which you should use if you don't have a specific reason to not to:

void fun(const void *param);
hyde
  • 60,639
  • 21
  • 115
  • 176
0

does "void * const ptr" matter for functions paramter?

The top-level qualifiers like const, volatile are simply ignored when resolving a function call. That is, during overload resolution the top-level const used in the parameter param of your example doesn't matter. That is the top-level const doesn't change signature of the function.

void fun(void * const param); // first declaration

void fun(void * param);       // re-declaration of the same function above

But after a suitable function has been selected(using function overloading), in case 1(void * const param) the parameter param cannot be modified inside the body of the function while in case 2(void * param) nothing stops you from modifying param like by assigning to it.

Jason
  • 36,170
  • 5
  • 26
  • 60
  • It is not only that overload resolution doesn't distinguish between the functions. The declarations declare the same function. – user17732522 May 27 '22 at 13:16
  • @user17732522 Yes, i just gave an example that uses overload resolution. I never meant to imply that it is limited to just overload resolution. Note that i wrote the top-level `const` doesn't change the signature. – Jason May 27 '22 at 13:17