Branko Čibej <[email protected]> writes:
> There is something fishy going on here. For example, this is the prototype
> for strstr:
>
> char *strstr(const char*, const char*);
The relevant change here could be the C23 proposal "N3020 - Qualifier-
preserving Standard Functions", which updated these functions to preserve
const qualifiers [1, 2]:
QChar *strstr (QChar *s1, const char *s2);
[where QChar stands for "qualified char"]
The prototype `char *strstr (const char*, …)` seems to have been a workaround
for the lack of function overloading in C. But the downside is that it does
not preserve constness and effectively works like an implicit const_cast.
> + char *p = NULL;
> char *ep = NULL;
> int sd;
>
> This makes no sense. Not only is 'p' already const, nothing is being
> modified through '*p' but something _is_ being modified through '*ep'.
I think the underlying question here and in similar cases is how the non-const
`char* ep` was obtained from `const char *p` in the first place.
In trunk, the const qualifier seems to be silently stripped away when passing
the pointer to functions like strstr() or strchr():
ep = strchr(p, '\n');
Type-wise, this is equivalent to:
ep = (char*)p;
and it's problematic, because it discards the const from the original pointer.
To some extent, I would say that using `const char *` is even misleading if
it's the only pointer available, as it obscures the fact that the data
eventually get modified without any explicit typecasts:
const char *keyword = APR_ARRAY_IDX(keyword_tokens, i, const char *);
/* The only pointer we had originally was const. */
if (expand_custom_keywords)
{
char *sep;
sep = strchr(keyword, '=');
if (sep)
{
*sep = '\0'; /* But then the data is modified here
without typecasts */
[1]:
https://thephd.dev/c23-is-coming-here-is-what-is-on-the-menu#n3020---qualifier-preserving-standard-functions
[2]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3020.pdf
Thanks,
Evgeny Kotkov