I encountered a problem at work today regarding const propagation in structs.
I was trying to add some const correctness to old code when I ran into an issue where two different compilers disagreed, GCC and IAR.
I think it boils down to whether adding const to a struct variable makes pointer members <type>* const or const <type>* const.
Minimal example:
struct S
{
char* p;
};
void f(const struct S* s)
{
char* non_const_char = s->p;
*non_const_char = 'a'; // Modyfing data that could be argued being part of const struct
}
GCC allows this code, but IAR fails saying that the assignment non_const_char can't be made, because
value of type "char const *" cannot be assigned to an entity of type "char *"
According to multiple SO questions GCC is correct, for example Scope of 'const' for pointers to protect underlying members of struct in C . This is also corroborated by cppreference.
However, I'm not standardese-fluent enough to parse which part of the standard actually says that const-qualification propagates to the struct members, but not to the types pointed to by member-pointers. Can anyone show me/quote what part states this? And has this ever changed with different standard versions?
*sis const-qualified, sos->pis const-qualified. However*s->p(i.e.*(s->p)) is not const-qualified. There should be no problem withchar* non_const_char = s->p;as it is just initializing achar *object with achar *value. There should be no problem with*non_const_char = 'a';or*s->p = 'a';as it is assigning acharvalue (after conversion fromint) to a non-const-qualifiedcharobject.s->p(by C17 6.5.2.3 paragraph 4) makes the assignments->p = "hello";a constraint violation (by C17 6.5.16 paragraph 2) because the left-hand side is not modifiable (by C17 6.3.2.1 paragraph 1), but that does not apply to*s->p = 'h';orstrcpy(s->p, "hello");.s->pischar * const, notchar const *. That error message is wrong.const.