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

但我认为这是不对的a,函数b中的参数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

4 回答 4

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

现在好啦。您必须将a和的地址b放在printf参数中,因为有char**.

于 2013-07-02T15:08:07.603 回答
1

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

转换时,编译器会尝试将您的*awhich解释char为指向 char 的指针,因此当执行转换时,您*sa最终会成为 BadPtr,因为它无法从 tochar转换char *

所以strcmp()你有两个 BadPtr。

于 2013-07-02T15:13:25.573 回答
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 被解释为内存地址。将“hello”与“bye”进行比较实际上是将地址 0x67 处的字符串与地址 0x62 处的字符串进行比较,这将发生段错误。

将 &a 和 &b 传递给您的比较函数,使其不会出现段错误。

于 2013-07-02T15:13:57.073 回答
0

两个版本都应该工作,但是,对于“campare_names”函数的第二个版本,您应该在调用函数时将一个附加指针传递给每个 char 指针。

但是,您的函数版本是正确的,只有在您期望函数会更改指针位置或指向的数据时,才有意义使用双指针参数。在这种情况下,由于 strcmp 函数只读取 char* 数据而不对其进行任何更改,因此您不需要额外的指针。

于 2013-07-02T15:17:20.203 回答