1

在下面的代码中,一旦我删除了比较字符串的注释部分,我就会遇到 seg 11 错误。我无法理解为什么!其余代码工作正常。任何帮助表示赞赏!

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

int compare_scores_desc(const void* scorea, const void* scoreb){
int a = *(int*)scorea;
int b = *(int*)scoreb;
return a-b;
}

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

int main(int argc, char* argv[]){
int scores[7] = {456,234,65,563,67,19,100};
int i;
qsort(scores,7,sizeof(int),compare_scores_desc);
puts("\nThese are the scores in order : \n");
for(i=0;i<7;i++)
    printf("%i\n",scores[i]);
char *names[] = {"Krishna","Rama","Bhishma","Arjuna"};
/*qsort(names,4,sizeof(char*),compare_names);*/
puts("------------------");
puts("The names in order are : \n");
for(i=0;i<4;i++)
    printf("%s\n",names[i]);
return 0;
}
4

2 回答 2

6

compare_names()中,您在强制转换后不恰当地取消引用参数。局部变量的类型是 type char **,但您将参数强制转换为char **并取消引用会导致char *.

namea并且nameb是指向在 . 中names[]声明的数组元素的指针main()。这意味着,它们的类型实际上是指向char *. 当您取消引用这些参数但将它们分配给 achar **时,您会导致局部变量将char *a 视为 a char **(您的编译器应该已向您发出有关此问题的诊断警告)。现在,您获取一个指针值 a char *,并在将其传递给 时取消引用它strcmp()。这导致程序将sizeof(char *)字符串的字节视为函数的指针值strcmp()。由于由重新解释为指针值的可打印字符组成的 4 或 8(或其他sizeof(char *))字节很少产生有效的指针,当strcmp()尝试使用这些指针时,会发生分段错误。

一种可能的解决方法是在初始化局部变量时不取消引用。但是,参数是const void *,因此如果将局部变量声明为指向const类型的指针,则可以完全避免强制转换:

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

请注意,compare_scores_desc()如果a - b导致有符号整数溢出,您的实现将失败。例如,如果aINT_MAXb-1。您应该修复您的实现以适用于所有情况。

int compare_scores_desc(const void* scorea, const void* scoreb){
const int *a = scorea;
const int *b = scoreb;
return (*a > *b) - (*a < *b);
}
于 2013-08-14T21:04:00.840 回答
2

问题出在您的字符串比较函数中,这可能是修复它的最小方法:

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

nameanameb参数是指向字符串向量的指针。您了解这一点,这就是您使用该char **类型的原因。

但是,您在函数中所要做的就是char *从该数组中检索指针。这些char *指针已经是字符串。您不必再次取消引用它们;只需将它们传递给strcmp.

您的原始代码存在约束冲突,需要进行诊断。那应该已经提示你了:

/* originally */
char** a = *(char**)namea; /* error: initialization from incompatible type */

您正在取消引用 a char **,这会产生char *,但是您将其存储在 a 中 char **并再次取消引用,从而错误地将字符数据视为指针。

于 2013-08-15T00:16:58.020 回答