[英]QSORT function in C
In the following code, once I remove the commented part which compares strings, I am getting a seg 11 fault. 在下面的代码中,一旦删除了比较字符串的注释部分,就会出现seg 11错误。 I am unable to understand why!
我不明白为什么! Rest of the code is working fine.
其余代码工作正常。 Any help is appreciated!
任何帮助表示赞赏!
#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;
}
In compare_names()
, you are inappropriately dereferencing the arguments after the cast. 在
compare_names()
,您在转换后不适当地取消引用了参数。 The types for the local variables are type char **
, but you are casting the arguments as char **
and dereferencing that results in a char *
. 局部变量的类型为
char **
类型,但是您正在将参数强制转换为char **
并取消引用,从而导致char *
。
namea
and nameb
are pointers to the elements of your array names[]
declared in main()
. namea
和nameb
是指向在main()
声明的数组names[]
的元素的指针。 That means, their types are actually pointer to char *
. 这意味着它们的类型实际上是指向
char *
指针。 When you dereferenced these arguments but assigned them to a char **
, you cause the local variable to treat the char *
as a char **
(your compiler should have issued a diagnostic warning you about this problem). 当您取消引用这些参数但将它们分配给
char **
,会导致局部变量将char *
视为char **
(您的编译器应已针对此问题发出诊断警告)。 Now, you take a pointer value that is a char *
, and dereference it when you pass it to strcmp()
. 现在,您获取一个为
char *
的指针值,并在将其传递给strcmp()
时取消引用。 This causes the program to treat sizeof(char *)
bytes of the string as a pointer value for the strcmp()
function. 这导致程序将字符串的
sizeof(char *)
字节视为strcmp()
函数的指针值。 Since 4 or 8 (or whatever sizeof(char *)
is) bytes consisting of printable characters reinterpreted as a pointer value rarely yields a valid pointer, when strcmp()
tries to use those pointers, a segmentation fault occurs. 由于由可打印字符组成的4或8个字节(或任何
sizeof(char *)
是sizeof(char *)
被重新解释为指针值的字节很少产生有效的指针,因此当strcmp()
尝试使用这些指针时,会发生分段错误。
One possible fix is to not dereference when you initialize your local variables. 一种可能的解决方法是在初始化局部变量时不取消引用。 However, the arguments are
const void *
, so you can avoid the cast altogether if you declare your local variables to be a pointer to a const
type: 但是,参数是
const void *
,因此,如果将局部变量声明为const
类型的指针,则可以完全避免进行const
:
int compare_names(const void* namea, const void* nameb){
char* const * a = namea;
char* const * b = nameb;
return strcmp(*a,*b);
}
Note that your implementation of compare_scores_desc()
fails if a - b
results in signed integer overflow. 请注意,如果
a - b
导致有符号整数溢出,则compare_scores_desc()
实现将失败。 For example, if a
is INT_MAX
and b
is -1
. 例如,如果
a
为INT_MAX
且b
为-1
。 You should fix your implementation to work for all cases. 您应该修复您的实现以在所有情况下都可以使用。
int compare_scores_desc(const void* scorea, const void* scoreb){
const int *a = scorea;
const int *b = scoreb;
return (*a > *b) - (*a < *b);
}
The problem is in your string comparison function, and here is probably the minimal way to fix it: 问题出在您的字符串比较函数中,这可能是修复它的最小方法:
int compare_names(const void* namea, const void* nameb){
char* a = *(char**)namea;
char* b = *(char**)nameb;
return strcmp(a,b);
}
The namea
and nameb
arguments are pointers into the string vector. namea
和nameb
参数是指向字符串向量的指针。 You understand this, which is why you used the char **
type. 您了解这一点,这就是为什么使用
char **
类型的原因。
However, all you have to do in the function is retrieve the char *
pointers from that array. 但是,该函数要做的就是从该数组中检索
char *
指针。 These char *
pointers are already strings. 这些
char *
指针已经是字符串。 You do not have to dereference them again; 您不必再次取消引用它们; just pass them to
strcmp
. 只需将它们传递给
strcmp
。
Your original code has a constraint violation which requires a diagnostic. 您的原始代码有违反约束的情况,需要进行诊断。 That should have tipped you off:
那应该告诉你:
/* originally */
char** a = *(char**)namea; /* error: initialization from incompatible type */
You're dereferencing a char **
, which produces char *
, but you're storing that in a char **
again and dereferencing again, thereby wrongly treating the character data as a pointer. 您正在取消引用产生
char *
的char **
,但是您将其再次存储在char **
并再次取消引用,从而错误地将字符数据视为指针。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.