There are two different sides related to const
with a pointer S* p
.
- Is it allowed to change the pointer? Example:
p=5;
- Is it allowed to change the object pointed to? Example:
p->x = 5;
These are the four possibilities:
T* p
: both changes allowedconst T* p
: object can not be changedT* const p
: pointer can not be changedconst T* const p
: neither object nor pointer can be changed
In your example void funct1(const tS * const i_pS, tS * const o_pS)
this means the following:
- You are not allowed to change the pointers
i_pS
ando_pS
. - You are not allowed to change the object pointed to by
i_pS
. - You are allowed to change the object pointed to by
o_pS
.
The first condition looks rather pointless, so probably this
void funct1(const tS* i_pS, tS* o_pS)
is more readable.
Regarding the second and third case where you have two pointers which point to the same part of an object: Be careful that you do not make wrong assumptions in the code, for example that the object pointed to by the const pointer is actually not changing.
Remember, a const pointer does never mean the object is not changing, only that you are not allowed to change it via that pointer.
Example for problematic code:
void foo(const S* a, S* b) {
if(a->x != 0) {
b->x = 0;
b->y = 5 / a->x; // why is a->x suddenly 0 ??
}
}
S s;
foo(&s, &s);
Regarding undefined behaviour and sequence points. I would advice to read this answer: Undefined behavior and sequence points
So for example the expression i = a->x + (b->x)++;
is definitely undefined behavior if a
and b
point to the same object.
A function void funct1(const tS* i_ps, tS* o_pS)
which is called as funct1(&my_struct, &my_struct);
is an open door to confusion and errors.
The C library also knows that problem. Consider for example memcpy
and memmove
.
So I would advice to build your functions such that you can be sure that no undefined behavior can occur. The most drastic measure would be to make a complete copy of the input struct. This has overhead, but in your specific case perhaps it is enough to copy only some small part of the input argument.
If the overhead is too big, specifically state in the function documentation that it is not allowed to give the same object as input and output. Then, if possible and necessary, create a second function with the necessary overhead to handle the case where input and output are the same.