簡體   English   中英

C中的QSORT函數

[英]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 *

nameanameb是指向在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()實現將失敗。 例如,如果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);
}

問題出在您的字符串比較函數中,這可能是修復它的最小方法:

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 */

您正在取消引用產生char *char ** ,但是您將其再次存儲在char **並再次取消引用,從而錯誤地將字符數據視為指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM