Problem using bsearch with array of strings

I get some confusing behavior trying to use the c built-in bsearch in an array of strings in C. Here is the code. I know that you can use the built-in strcmp to search for string arrays, but I turned on myStrCmp for debugging purposes because I did not know why it did not work.

const char *stateNames[] = {"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "Washington DC", "West Virginia", "Wisconsin", "Wyoming"};

int myStrCmp(const void *s1, const void *s2) {
  printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, (char *)s1, s2, (char *)s2);
  return strcmp(s1, s2);
}

int determineState(char *state) {
  printf("state: %s\n", state);
  for(int i = 0; i < 51; i++) 
    printf("stateNames[%i](%p): %s\n", i, &(stateNames[i]), stateNames[i]);

  char *found = (char *) bsearch(state, stateNames, 51, sizeof(char *), myStrCmp );

  if(found == NULL)
    return -1;

  return 0;
}

and these are some of the results when this function is called to search for Alabama.

stateNames[0](0x618440): Alabama
stateNames[1](0x618448): Alaska
stateNames[2](0x618450): Arizona
...
stateNames[24](0x618500): Missouri
stateNames[25](0x618508): Montana
stateNames[26](0x618510): Nebraska
stateNames[27](0x618518): Nevada
stateNames[28](0x618520): New Hampshire
stateNames[29](0x618528): New Jersey
stateNames[30](0x618530): New Mexico
stateNames[31](0x618538): New York
stateNames[32](0x618540): North Carolina
stateNames[33](0x618548): North Dakota
stateNames[34](0x618550): Ohio
stateNames[35](0x618558): Oklahoma
stateNames[36](0x618560): Oregon
stateNames[37](0x618568): Pennsylvania
stateNames[38](0x618570): Rhode Island
stateNames[39](0x618578): South Carolina
stateNames[40](0x618580): South Dakota
stateNames[41](0x618588): Tennessee
stateNames[42](0x618590): Texas
stateNames[43](0x618598): Utah
stateNames[44](0x6185a0): Vermont
stateNames[45](0x6185a8): Virginia
stateNames[46](0x6185b0): Washington
stateNames[47](0x6185b8): Washington DC
stateNames[48](0x6185c0): West Virginia
stateNames[49](0x6185c8): Wisconsin
stateNames[50](0x6185d0): Wyoming
myStrCmp: s1(0x415430): Alabama, s2(0x618508): 
                                               UA
myStrCmp: s1(0x415430): Alabama, s2(0x618570): A
myStrCmp: s1(0x415430): Alabama, s2(0x618540): PUA
myStrCmp: s1(0x415430): Alabama, s2(0x618528): 1UA
myStrCmp: s1(0x415430): Alabama, s2(0x618538): GUA
myStrCmp: s1(0x415430): Alabama, s2(0x618530): <UA

As you can see, the places visited by bsearch during its search should have valid strings (as it was checked before calling bsearch), but the output, if you try to print char * in this place, is garbage. Can anyone see my mistake? By the way, I get the same bad behavior (but don’t understand how it should be) when I call bsearch with the final parameter set to:

(int(*)(const void*, const void*))strcmp

!

+5
2

const char *, bsearch() . , const char * const * .

int myStrCmp(const void *s1, const void *s2) {
  const char *key = s1;
  const char * const *arg = s2;
  printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, key, s2, *arg);
  return strcmp(key, *arg);
}
+7

( ) . / const . myStrCmp , . , , . , , , .

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


const char *stateNames[] = {"Alabama", "Alaska", "Arizona", "Arkansas","California", "Colorado", "Connecticut", "Delaware", "Florida","Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "Washington DC", "West Virginia", "Wisconsin", "Wyoming"};

int myStrCmp(const void *s1, const void *s2) {
    printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, *(char **)s1, s2, *(char**)s2);
    return strcmp(*(char **) s1, *(char **) s2);
}

int determineState(char *state) {
    printf("state: %s\n", state);

    for(int i = 0; i < 51; i++)
        printf("stateNames[%i](%p): %s\n", i, &(stateNames[i]), stateNames[i]);

    char **found = (char **) bsearch(&state, stateNames, 51, sizeof(char *), myStrCmp );

    if(found == NULL){
        return -1;
    } else {
        printf("Found it!: %s\n", *found);

    }

    return 0;
}

int main(int argc, const char * argv[]) {
    determineState("Alabama");

}
+1

All Articles