[英]QSORT function in C
在下面的代碼中,一旦刪除了比較字符串的注釋部分,就會出現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;
}
在compare_names()
,您在轉換后不適當地取消引用了參數。 局部變量的類型為char **
類型,但是您正在將參數強制轉換為char **
並取消引用,從而導致char *
。
namea
和nameb
是指向在main()
聲明的數組names[]
的元素的指針。 這意味着它們的類型實際上是指向char *
指針。 當您取消引用這些參數但將它們分配給char **
,會導致局部變量將char *
視為char **
(您的編譯器應已針對此問題發出診斷警告)。 現在,您獲取一個為char *
的指針值,並在將其傳遞給strcmp()
時取消引用。 這導致程序將字符串的sizeof(char *)
字節視為strcmp()
函數的指針值。 由於由可打印字符組成的4或8個字節(或任何sizeof(char *)
是sizeof(char *)
被重新解釋為指針值的字節很少產生有效的指針,因此當strcmp()
嘗試使用這些指針時,會發生分段錯誤。
一種可能的解決方法是在初始化局部變量時不取消引用。 但是,參數是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);
}
請注意,如果a - b
導致有符號整數溢出,則compare_scores_desc()
實現將失敗。 例如,如果a
為INT_MAX
且b
為-1
。 您應該修復您的實現以在所有情況下都可以使用。
int compare_scores_desc(const void* scorea, const void* scoreb){
const int *a = scorea;
const int *b = scoreb;
return (*a > *b) - (*a < *b);
}
問題出在您的字符串比較函數中,這可能是修復它的最小方法:
int compare_names(const void* namea, const void* nameb){
char* a = *(char**)namea;
char* b = *(char**)nameb;
return strcmp(a,b);
}
namea
和nameb
參數是指向字符串向量的指針。 您了解這一點,這就是為什么使用char **
類型的原因。
但是,該函數要做的就是從該數組中檢索char *
指針。 這些char *
指針已經是字符串。 您不必再次取消引用它們; 只需將它們傳遞給strcmp
。
您的原始代碼有違反約束的情況,需要進行診斷。 那應該告訴你:
/* originally */
char** a = *(char**)namea; /* error: initialization from incompatible type */
您正在取消引用產生char *
的char **
,但是您將其再次存儲在char **
並再次取消引用,從而錯誤地將字符數據視為指針。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.