在C中正确实现比较器功能不能按预期工作

时间:2013-07-02 15:00:47

标签: c pointers

我正在测试比较器功能的实现。所以这是我的代码工作

#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;
}

但是我不认为这是正确的,因为ab函数的compare_names参数应该变成指向char的指针。正如我读过的一本书所指出的,compare_names函数的正确代码是

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

但是当我运行代码时,我遇到了分段错误(核心转储)。

我在这里缺少什么?

编辑:我在Linux x64上使用gcc。

4 个答案:

答案 0 :(得分:1)

#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;
}

现在没关系。您必须将ab的地址放在printf参数中,因为它已投放到char**

答案 1 :(得分:1)

char** sa = (char**) a;这句话说:“如果您对sa两次进行指导,最终会得到一个char”问题在于,因为您的a是指针char你不能两次指责它。所以你正在做的铸造通常是错误的。

在进行转换时,编译器会尝试将*a解释为char作为指向char的指针,因此在执行转换时,*sa最终成为BadPtr,因为它失败了要从char转换为char *

所以在strcmp()你有两个BadPtr。

答案 2 :(得分:1)

您传递的是char *参数,而不是char **参数。您发布的显示char **的示例代码执行以下操作:

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.

但是您将char *参数传递给比较函数,因此解除引用最终会将char类型的参数传递给strcmp。由于它需要指针,因此char被解释为内存地址。比较&#34;你好&#34; to&#34; bye&#34;实际上将地址0x67处的字符串与地址0x62处的字符串进行比较,这将是段错误。

将&amp; a和&amp; b传递给您的比较功能,使其不会出现段错误。

答案 3 :(得分:0)

然而,两个版本都适用于&#34; campare_names&#34;的第二个版本。函数,你应该在调用函数时传递一个指向每个char指针的aditional指针。

但是你的函数版本是正确的,当你期望函数将改变指针位置或被指向的数据时,它只能使用双指针参数。在这种情况下,由于strcmp函数只读取char *数据并且没有对其进行任何更改,因此您不需要一个aditional指针。