I have a structure with a pointer to something. I was expecting that accessing this pointer via a pointer-to-const-struct to the struct gives me a pointer-to-const-something. But gcc does not produce a warning in this case:
#include <stdlib.h>
struct S {
void* ptr;
};
struct S* create(void)
{
struct S* S = malloc(sizeof(*S));
S->ptr = malloc(sizeof(int));
return S;
}
void some_func(void* p);
int main(void)
{
struct S* S = create();
const void* ptr = S->ptr;
const struct S* SC = S;
some_func(ptr); // warning as expected
some_func(SC->ptr); // no warning
}
So is SC->ptr
actually a const void*
? I always assumed but now I'm confused. Is there a possibility to get a warning in this case?
CodePudding user response:
SC->ptr
is a void * const
. It is not a const void *
or const void * const
.
const struct S* SC = S;
defines SC
to be a pointer to a struct S
that is const
-qualified. The fact the structure is const
-qualified means you should not modify the structure. The structure contains a member ptr
of type void *
. Because the structure is const
-qualified, its members are const
-qualified. That means you should not change ptr
. Its type is void * const
.
However, that does not affect what ptr
points to. Regardless of whether ptr
itself is const
-qualified, it points to void
, not to const void
.
The C standard does not provide good means of working with multiple versions of a structure in which one version has members that point to non-const
types and the other has members that point to const
types. In general, there is no good way to convert one such structure into the other type.
CodePudding user response:
So is SC->ptr actually a
const void*
?
No. SC->ptr
is an expression designating an object of type void *
, which expression you may not use to modify the value of that object. (There might, in principle, be other expressions designating the same object by which it could be modified.) This is similar to, but not exactly the same as, a void * const
-- the pointer cannot be modified. There is no implication on modifying the data to which it points.
some_func(SC->ptr); // no warning
[...]
Is there a possibility to get a warning in this case?
C semantics provide no particular reason to diagnose anything suspicious or wrong about that case, because again, it is the pointer that must not be modified, not the data to which it points. And because the pointer is passed by value, there is no way for the function to modify it.