首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >泛型C函数的字符串比较函数

泛型C函数的字符串比较函数
EN

Stack Overflow用户
提问于 2016-01-30 08:08:23
回答 2查看 913关注 0票数 2
代码语言:javascript
复制
void *idealGenericLSearch(void *key, void *base, int numElem, int elemSize,
                          int (*cmpfn)(void *, void *)) {
    for (int i = 0; i < numElem; i++) {
        void *elemAddr = (char *)base + (i * elemSize);
        if (cmpfn(key, elemAddr) == 0)
            return elemAddr;
    }
    return NULL;
}

这是我正在使用的通用线性搜索函数。我正在搜索一个char *的数组。下面是我的比较函数:

代码语言:javascript
复制
int myStrCmp(void *vp1, void *vp2) {
    char *s1 = *(char**)vp1;
    char *s2 = *(char**)vp2;
    return strcmp(s1, s2);
}

我主要是这样称呼它的:

代码语言:javascript
复制
char *notes[] = { "Ab", "F#", "B", "Gb", "D" };
char *keyNote = "Gb";
char **foundNote = idealGenericLSearch(&keyNote, notes, 5, sizeof(char *), myStrCmp);
if (foundNote) {
    printf("found the note: %s\n", *foundNote);
} else {
    printf("did not find note\n");
}

我无法理解的是,如果我去掉了(char**)转换和取消引用,为什么我的比较函数仍然同样工作。如果我像这样写cmpfn

代码语言:javascript
复制
int myStrCmp(void *vp1, void *vp2) {
    char *s1 = vp1;
    char *s2 = vp2;
    return strcmp(s1, s2);
}

还能用。当lsearchelemAddr传递给这个比较函数时,它应该是一个指向char*的指针,在这种情况下,在比较函数中,我将传递strcmp char**

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-30 08:32:09

你的问题很有趣!人们可能会预料到一些未定义的行为,甚至是崩溃。这确实是偶然的,但其原因如下:

在测试中使用字符串文字:

代码语言:javascript
复制
char *notes[] = { "Ab", "F#", "B", "Gb", "D" };
char *keyNote = "Gb";

您的编译器很可能共享字符串文本,因此notes[3]中的指针具有与keyNote相同的值。

在使用线性搜索时,您将执行strcmp,不是对字符串,而是对它们的地址。地址可能包含一个空字节,如果您的体系结构是小endian,那么地址中的重要非空字节将首先出现。有了这些机会,对于所有其他条目来说,strcmp((char*)notes[3], (char*)&keyNote)确实是0和非0

您可以通过测试以下内容来验证这一理论:

代码语言:javascript
复制
char *notes[] = { "Ab", "F#", "B", "Gb", "D" };
char *keyNote = strdup("Gb");

如果keyNote中有一个不同的指针,一般搜索就会失败。

票数 2
EN

Stack Overflow用户

发布于 2016-01-30 08:28:27

这就是为什么第二个版本的myStrCmp“工作”。第一个版本是您想要的,它将按预期对字符串进行比较。另一方面,第二个版本是将保存字符串地址的指针视为字符串本身。因此,它将指针逐字节地进行比较,就好像它们是字符串一样。如果指针是不同的,那么它很可能会比较为不相等(除非两个指针在它们不同之前包含零字节)。但是如果指针是相同的,那么在遇到不同字节之前,如果在指针中或在指针之后遇到零字节,那么它们就有可能比较相等。

那么,为什么两个"Gb"指针是相同的呢?因为编译器识别它们是相同的字符串,并为两个引用分配一个字符串。

不用说,这是一个非常不明确的行为,因此,分析为什么它有时工作是纯粹的学术。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35099513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档