Reputation: 115
My program needs to determine whether or not a pointer s1 has any characters from s2 in it and then return a pointer to that position in s1, otherwise return NULL.
#include <stdio.h>
char * strpbrk(const char *, const char *);
int main(void){
const char *s1 = "hello";
const char *s2 = "world";
printf("Repeated character in s1 is %p", *strpbrk(s1, s2));
}
char * strpbrk(const char * s1, const char * s2){
char *p1, *p2;
p1 = s1;
p2 = s2;
for(; *p1 != '\0'; p1++){
for(; *p2 != '\0'; p2++){
if(*p1 == *p2){
break;
}
else{
return '\0';
}
}
}
return p1;
}
Keep getting this error:
test.c: In function ‘strpbrk’:
test.c:16:5: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
p1 = s1;
^
test.c:17:5: warning: assignment discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
p2 = s2;
Upvotes: 1
Views: 213
Reputation: 213276
This is an inconsistency in several of the standard library functions, strpbrk
, strstr
etc. The standard demands that they return a non-constant pointer to the found item inside a const-qualified string. What the standard committee was smoking when they decided to add const-correctness to the parameters of these library functions, but not to the return types, I have no idea.
There is no way that you can reliably implement such a function in standard C, since you are not allowed to convert from a "qualified pointer to type" to a "pointer of type". C11 6.7.6.1:
For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.
This is why you keep getting compiler warnings. Violating this rule is listed as undefined behavior by the (non-normative) Annex J:
Two pointer types that are required to be compatible are not identically qualified, or are not pointers to compatible types (6.7.6.1).
So the answer to your question is that functions like strpbrk
and strstr
cannot get implemented safely and portably in standard C. They will have to be implemented by using either non-standard language extensions or another programming language.
The sound solution is to ignore the function declaration as specified by the standard and use a rational one instead. Either
char* strpbrk_rw (char* s1, const char* s2); // read/write parameter
or
const char* strpbrk_ro (const char* s1, const char* s2); // read-only parameter
Upvotes: 1
Reputation: 33273
The best way to get rid of the compiler warning is to change p1
and p2
to pointers to const char and then add a cast when you return p1
. That way readers of the code will see that you don't intend to modify the string arguments.
There also were a couple of bugs in the implementation that I (hopefully) ironed out.
char * strpbrk(const char * s1, const char * s2) {
const char *p1, *p2;
for (p1 = s1; *p1 != '\0'; p1++) { // out is a label
for (p2 = s2; *p2 != '\0'; p2++) {
if (*p1 == *p2) {
// Match found
return (char*)p1;
}
}
}
// No match found
return NULL;
}
Upvotes: 0