kaneda
kaneda

Reputation: 6187

Correct implementation of comparator function in C not working as expected

I was testing an implementation of a comparator function. So here's my code that worked

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

int compare_names(const void* a, const void* b)
{
    char* sa = (char*) a;
    char* sb = (char*) b;
    return strcmp(sa, sb);
}  

int main()
{
    char *a = "Bianca";
    char *b = "Ana";
    printf("Comparing %s with %s returns: %i\n", a, b, compare_names(a, b)); 
    return 0;
}

But I don't think it's right as a and b arguments at compare_names function should turn out to be a pointer to a pointer of char. As pointed in a book I've read, the correct code for the compare_names function would be

int compare_names(const void* a, const void* b)
{
    char** sa = (char**) a;
    char** sb = (char**) b;
    return strcmp(*sa, *sb);
}

But when I ran the code I got a segmentation fault (core dumped).

What am I missing here?

EDIT: I'm using gcc on Linux x64.

Upvotes: 1

Views: 192

Answers (4)

andre.barata
andre.barata

Reputation: 663

Both versions should work, however, for the second version of the "campare_names" function, you should pass an aditional pointer to each of the char pointers when calling the function.

However your version of the function is correct, it only makes sence to use double pointer parameters, when you are expecting that a function wil alter the pointer position or data being pointed. In this case, since the strcmp function only reads the char* data and doesn't make any changes to it, you don't need an aditional pointer.

Upvotes: 0

user539810
user539810

Reputation:

You are passing char* arguments, not char** arguments. The example code you posted showing char** does the following:

1. Change generic pointer to a pointer to a string.
2. Compare the strings by dereferencing the char** arguments, meaning you're passing char* arguments to strcmp and return the result.

But you passed char* arguments to your comparison function, so the dereferencing ends up passing arguments of type char to strcmp. Since it expects pointers, the char is interpreted as a memory address. Comparing "hello" to "bye" actually compares the string at address 0x67 to the string at address 0x62, which will segfault.

Pass &a and &b to your comparison function to make it not segfault.

Upvotes: 1

Alexandru Barbarosie
Alexandru Barbarosie

Reputation: 2992

char** sa = (char**) a; This line says: "If you direference twice your sa you will end up with a char" The problem is that since your a is a pointer to char you can not direference it twice. So the casting you are doing is generally wrong.

When casting, the compiler trys to interpret your *a which is a char as a pointer to char so when the conversion is performed your *sa ends up being a BadPtr since it fails to convert from char to char *.

So in your strcmp() you have two BadPtr.

Upvotes: 1

nouney
nouney

Reputation: 4411

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

int compare_names(const void* a, const void* b)
{
    char** sa = (char**) a;
    char** sb = (char**) b;
    return strcmp(*sa, *sb);
} 

int main()
{
    char *a = "Bianca";
    char *b = "Ana";
    printf("Comparing %s with %s returns: %i\n", a, b, compare_names(&a, &b)); 
    return 0;
}

Now it's ok. You have to put the address of a and b in the printf parameters, since there are casted to char**.

Upvotes: 1

Related Questions