This is the mail archive of the libc-alpha@cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: glibc-2.0.100: bits/string2.h nits


Horst von Brand writes the following:
>
>Just some nagging at /usr/include/bits/string2.h, line 825: egcs is
>(justifiably) annoyed by the cast at the return of this function.  There

The problem is that there are some functions in C, including strpbrk and
strchr, which cannot be implemented in a clean way because of the way they
abuse pointers. They can't be improved because their interfaces are defined
by the relevant standards in a fundamentally broken way.

strchr is the simpler example, so I'll write it here to demonstrate:

char *strchr(const char *s, int c)
{
  while(*s && *s!=c)
    ++s;
  if(*s==c)
    return (char *)s;
  return NULL;
}

This function definition will trigger a -Wcast-qual warning. But how can we
fix it? The prototype is thrust upon us by the standard.

Here's why strchr must accept a const char * argument:

const char *foobar[]="foobar";
const char *bar=strchr(foobar, 'b');

And here's why it must return a non-const char *:

/* Suppose that mygetline() returns a pointer to some malloced space, and it
 * will abort if there is no \n */
char *line=mygetline(stdin);
strchr(line,'\n')[0]='\0';

And here's why the compiler can and should give a warning about the guts of
strchr:

const char *foobar[]="foobar";
strchr(foobar, 'b')[0]='\0'; /* segfault */

The complete story behind strchr is that it returns a pointer to modifiable
char if and only if it was passed a pointer to modifiable char. There is,
unfortunately, no way to express that rule in the form of a function
prototype. The warning about the ugly cast should be taken as the compiler
telling you that the function strpbrk (like strchr) was misdesigned. (Or
perhaps that it was designed for a C language in which the const keyword
either did not exist yet or was not taken seriously)

The right way to design it is to have it return an integer (ptrdiff_t probably)
offset into the search string. Then you could add that on to the pointer you
passed, and it would have the correct constness through the wonder of pointer
arithmetic. But it's far too late for that now. Now, all we can do is resign
ourselves to the fact that <string.h> and its subordinate headers are not the
place to look for clean interfaces.

That said, I have come up with a way to suppress the -Wcast-qual warning for
particular cases like these, where there is no way to truly fix them. Before
I tell you what it is, I must warn you:

1. It's ugly
2. It's platform-specific (but very easy to adapt)
3. It's really ugly
4. I'd love to hear some better ideas (which would be ANY other ideas)
5. You will need a barf bag

Here we go



Change (char *)s to (char *)(long)s

-- 
Alan Curry


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]