2016-09-29 52 views
0

我正在做一个使用C语言的代码练习。空指针奇点问题

如下代码,

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

int ACDSort(const void *p1, const void *p2); 
int Compare(const void *pKey, const void *pValue); 
int main(void) 
{ 
    char * strAry[4] = {"Hardware","Cookie","Boy","Power"}; 
    char * destStr = "Cookie"; 

    //qsort((void*)strAry, sizeof(strAry)/sizeof(char*), sizeof(char*), ACDSort); 

    char **ptrAdr = (char**)bsearch((void*)destStr, strAry, sizeof(strAry)/sizeof(char*), sizeof(char*), Compare); 

    printf("%s\n", *ptrAdr); 
} 

int Compare(const void *pKey, const void *pValue) { 
    char *key = ((char*)pKey); 
    char *value = *((char**)pValue); 
    return strcmp(key, value); 
} 

int ACDSort(const void *p1, const void *p2) { 

    char * n1 = *((char**)p1); 
    char * n2 = *((char**)p2); 
    int ret; 

    if (strlen(n1) > strlen(n2)) 
     ret = 1; 
    else if (strlen(n1) < strlen(n2)) 
     ret = -1; 
    else 
     ret = 0; 
    return ret; 
} 

我叫bsearch找到cookie的字符串。 问题是当我擦除//以基于字符串长度对数组进行排序时发生错误。 我不知道为什么错误被执行,因为我认为qsort无法对我的代码产生重大影响。

你能告诉我为什么错误发生时返回空指针擦除//的原因?

Ps。我使用qsortbsearch来熟悉指针变量。

+4

'bsearch'仅在数组已被排序时才有效 –

+1

请注意,对于'qsort()'和'bsearch()',您通常应该使用相同的比较函数。如果你必须使用不同的功能,你做错了什么。 –

+0

为什么对'qsort()'和'bsearch()'使用不同的函数? – sclee1

回答

5

bsearch使用二进制搜索,这就是为什么。二进制搜索需要对数据进行排序。按字母顺序对字符串数组进行排序,它将起作用。作为一个方面说明,你需要摆脱所有那些多余的强制转换,他们所做的只是隐藏潜在的错误。

工作程序修复和清理后:

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

int compare (const void* p1, const void* p2); 

int main (void) 
{ 
    const char* strAry[4] = {"Boy", "Cookie", "Hardware", "Power"}; 
    const char* key = "Cookie"; 

    char** ptrAdr = bsearch(key, 
          strAry, 
          sizeof(strAry)/sizeof(*strAry), 
          sizeof(*strAry), 
          compare); 

    printf("%s\n", *ptrAdr); 
} 

int compare (const void* p1, const void* p2) 
{ 
    const char* s1 = p1; 
    const char* s2 = *(const char* const*)p2; 

    return strcmp(s1, s2); 
} 

P2会const空指针结束的const char*,这就是为什么我们得到的看起来怪怪的追求常量,正确性时施放。

-1

类型的destStr可以改变为相同类型的strAry,例如:

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

int Compare(const void *pKey, const void *pValue) 
{ 
    char *key = *((char**)pKey); 
    char *value = *((char**)pValue); 
    return strcmp(key, value); 
} 

int main(void) 
{ 
    char * strAry[4] = { "Hardware", "Cookie", "Boy", "Power" }; 
    char * destStr[1] = { "Cookie" }; // Type changing 

    qsort(strAry, sizeof(strAry)/sizeof(char*), sizeof(char*), Compare); 

    char **ptrAdr = (char**)bsearch((void*)destStr, strAry, sizeof(strAry)/sizeof(char*), sizeof(char*), Compare); 

    printf("%s\n", *ptrAdr); 
} 

此外,如果使用C语言(和编译器)考虑直接使用strcmp作为比较两个元件回调函数。

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

/*int Compare(const void *pKey, const void *pValue) 
{ 
    char *key = *((char**)pKey); 
    char *value = *((char**)pValue); 
    return strcmp(key, value); 
}*/ 

int main(void) 
{ 
    char * strAry[4] = { "Hardware", "Cookie", "Boy", "Power" }; 
    char * destStr[1] = { "Cookie" }; // Type changing 

    //qsort(strAry, sizeof(strAry)/sizeof(char*), sizeof(char*), Compare); 
    qsort(strAry, sizeof(strAry)/sizeof(char*), sizeof(char*), strcmp); 

    //char **ptrAdr = (char**)bsearch((void*)destStr, strAry, sizeof(strAry)/sizeof(char*), sizeof(char*), Compare); 
    char **ptrAdr = (char**)bsearch(destStr, strAry, sizeof(strAry)/sizeof(char*), sizeof(char*), strcmp); 

    printf("%s\n", *ptrAdr); 
} 

注:

这种解决方案具有显示为一个缺点...

警告:使从兼容的指针类型 'bsearch' 的参数5 [默认启用]

但它的工作原理(我已经尝试过使用GCC版本4.8.2和MS Visual Studio 12.0)

+1

它可能在测试时工作,但它仍然是非法的,因为编译器试图告诉你。当简单包装器修复它时,不需要引入可能的问题。由于C中未定义的行为,因此您不能仅仅使用测试来确定某件事是否正常。 – user694733

+0

是的,这就像一个伎俩....所以,我留下可以使用的评论代码。 – VolAnd

+1

从int(*)(const char *)(const char *)'到int(*)(const void *)(const void *)的指针转换调用未定义的行为。如果'void *'和'char *'具有相同的表示形式,并且代码中没有指针别名优化,那么在运行时碰巧不存在调用约定差异的情况下,它将“运行”。 – Lundin