This seems to be a bug in gcc, fixed in a later release.
Here is a small program that I wrote to illustrate the problem.
#include <stdio.h> #include <string.h> int main(void) { const char message[] = "hello"; #ifdef ASCII_ONLY const char search_for[] = "h"; #else const char search_for[] = "Ʃ"; #endif char *non_const_message = strstr(message, search_for); if (non_const_message == NULL) { puts("non_const_message == NULL"); } else { puts(non_const_message); } }
When I compile it with
gcc -DASCII_ONLY -std=c99 -pedantic-errors cc -oc
(using gcc 4.8.2 on Linux Mint 17), it compiles without diagnostic messages, and the resulting program prints
hello
(I use -pedantic-errors because it causes gcc (attempt) to be a compatible ISO compiler.)
When I discard the -DASCII_ONLY , I get a compile-time error message:
cc: In function 'main': cc:11:31: error: initialization discards 'const' qualifier from pointer target type char *non_const_message = strstr(message, search_for);
The strstr function returns a result of type char* , not const char* . It takes two arguments const char* , and with the right search string, it can return the value of its first argument. This means that he can silently reject the const argument of his argument. I believe this is a flaw in the C standard library, but we probably stick to it. According to C implementations, there is no way to “fix” this flaw if they want to stay consistent; they can warn of the dangerous use of strstr , but they cannot reject a different legal code.
(The disadvantage could be avoided by dividing strstr into two functions with different names, taking const char* and returning a const char* , and the other take char* and return a char* . The 1989 ANSI Committee did not take the opportunity to do this, because because they didn’t think about it or because they didn’t want to break the existing code. C ++ solves it with two overloaded versions of strstr that were not possible for C.)
My first assumption was that gcc “magically” does something similar to what C ++ does, but examples that discard const using only ASCII characters do not trigger a diagnostic message. As my test program shows, the problem is triggered using a non-ASCII character in the string literal ( "Ʃ" , not "h" ).
When I use gcc 4.9.1 (which I installed from the source) and not gcc 4.8.2 (the default version installed on my system), the problem disappears:
$ gcc -DASCII_ONLY -std=c99 -pedantic-errors cc -oc && ./c hello $ gcc -std=c99 -pedantic-errors cc -oc && ./c cc: In function 'main': cc:11:31: error: initialization discards 'const' qualifier from pointer target type char *non_const_message = strstr(message, search_for); ^ $ gcc-4.9.1 -DASCII_ONLY -std=c99 -pedantic-errors cc -oc && ./c hello $ gcc-4.9.1 -std=c99 -pedantic-errors cc -oc && ./c non_const_message == NULL $
I no longer tracked the error, but you could find it in the list of gcc errors installed between 4.8.2 and 4.9.1.
For the code in question, you can avoid the problem by specifying pos as const char* rather than char* . It must be const char* anyway, as it points to an object that was defined as const .