On 3. 3. 26 14:53, Evgeny Kotkov wrote:
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.

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

Reply via email to