Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C99 remove stricmp() and strnicmp()?

Tags:

c

string

c99

Is the functions stricmp() and strnicmp() removed in C99? I always get warning implicit declaration of funtion stricmp() (and also strnicmp() ) when I try to compile it against C99. For example, the simple code below get me that warning.

#include<string.h>
#include<stdio.h>

char arr[100]="hello";
char arr2[100]="hEllo";

int main()
{
   int n=-1;
   printf("%d\n",n);
   n=strnicmp(arr,arr2,3);   // the same when use the function stricmp();
   printf("%d\n",n);

   getchar();
   return 0;
}

When I try to compile this piece of code against C99(gcc -Wall -std=c99 main.c -o main), I get that warning. But when I compile it without the -std=c99, no warning will be thrown. However, even though there is warning of implicit declaration, my code still work out right.

Why is that? Is that a bug? If not a bug, then what is exactly the change of C99 which make that warning happen?

like image 202
walkerlala Avatar asked Jun 09 '15 13:06

walkerlala


2 Answers

When code compiles with C99, it conform to the C99 standard, which does not have stricmp(). When code compile without C99 switch, it conforms to an unknown standard that implements stricmp(). (Given gcc without -std=c99, likely compiles to the C89/90 standard wihich allows implicit declarations.)

As @Joachim Pileborg commented, insensitive compares are not part of the C standard.

With C99 implicit functions require a diagnostic (a warning in this case). Without C99, the implicit use of the function generates no warning. The functions exists in this compiler's library - it is just a question of are the functions declared before use.

Easy enough to make your own:

int wal_stricmp(const char *a, const char *b) {
  int ca, cb;
  do {
     ca = (unsigned char) *a++;
     cb = (unsigned char) *b++;
     ca = tolower(toupper(ca));
     cb = tolower(toupper(cb));
   } while (ca == cb && ca != '\0');
   return ca - cb;
}

Note: When coding and trying to make A-Z match a-z, string insensitive compare routines tend to work uniformly well. But when trying to to order strings, things quickly get out of hand. "abc" vs. "_bc" can come before or after the other depending on if compassion was done as upper or lower case. '_', in ASCII, exists between the upper and lower case letters. With internationalization and locale issues, the situation becomes more complex. My code example uses a round-trip of conversion to cope with issues where the number of uppercase char does not have a 1-to-1 mapping with lowercase ones. IMO the complexities of robust case insensitive compares obliges the use of UTF encoding and its case definition.


[Edit 2020]

To cope with those forlorned non-2's complement as well as 2's complement platforms, a code correction is warranted. Earlier code would fold a +0 and -0 into an unsigned 0. Only the +0 should convert to 0. Proper to read the data as unsigned char rather than signed char and convert.

Note: the proper handle in non-2's complement is mostly academic now.

// ca = (unsigned char) *a++;
ca = *((unsigned char *) a++);
// also cb
like image 120
chux - Reinstate Monica Avatar answered Oct 13 '22 23:10

chux - Reinstate Monica


stricmp and strincmp are both non standard functions. They have never been a part of the C standard.

like image 21
haccks Avatar answered Oct 13 '22 23:10

haccks