On Tue, Mar 3, 2026 at 4:35 PM Branko Čibej <[email protected]> wrote:

> On 3. 3. 26 14:53, Evgeny Kotkov wrote:
>
> Branko Čibej <[email protected]> <[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.
>
>
> Yes, indeed, but we should be using -std=c90 in our build, and the C90
> stdlib doesn't have those new prototypes. Does the CMake build set the C
> standard parameters?
>
> +  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.
>
>
> Right. This is what we old-timer C programmers call a "horrible hack but
> it works" :)
>
> 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 */
>
>
> This is how the C standard library (used to) work ... a compromise. It's
> confusing and misleading and causes way too many bugs and is often abused
> for precisely this reason, to avoid explicit casts. That's one of the
> reasons why we force -std=c90.
>
> -- Brane
>
>
In fact, this warning also occurs with an explicit --std=c90. The QChar
thing is just a nice way to ensure that there are no implicit const_casts
from functions like strchr.

This might reveal real issues just like when a 'const char *' is explicitly
casted into a 'char *'. If an argument is given to a function and marked as
const, it assumes that the function does not change it.

By the way, it is true that CMake does not properly set up the C standard.

-- 
Timofei Zhakov

Reply via email to