我试图构建一个函数来检查一个特定的指针值是否存储在一个给定的数组中,我试图使这个函数与类型无关,所以我决定使用实现qsort()
时使用的方法,在这种方法中,传递一个函数指针来执行特定于类型的任务。
该函数如下所示:
int is_in(void* array, int size, void* pelement, int (*equals)(void* this, void* that)) {
for(int k = 0; k < size; k++) {
if(equals(array + k, pelement)) {
return 1;
}
}
return 0;
}
equals()
函数检查第二个参数是否等于第一个参数指向的值。
我需要实现的equals()
函数的一个特定实现与我创建的struct Symbol
类型有关。
int ptreq(void* ptr1, void* ptr2) {
return ((*((Symbol**) ptr1) == (Symbol*) ptr2));
}
struct Symbol
的定义如下:
enum SymbolType {
TERMINAL,
NONTERMINAL
} typedef SymbolType;
struct Symbol {
char* content;
SymbolType type;
} typedef Symbol;
void set_symbol(Symbol* pS, SymbolType type, char* content) {
pS->content = malloc(sizeof(content));
strcpy(pS->content, content);
pS->type = type;
}
然而,当我尝试用一个基本示例测试is_in()
时,我得到了不正确的结果。
#include <stdlib.h>
#include <stdio.h>
#include "string.h"
#include <stdarg.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
Symbol F, E;
set_symbol(&E, NONTERMINAL, "E");
set_symbol(&F, NONTERMINAL, "F");
Symbol** pptest = malloc(2*sizeof(Symbol*));
pptest[0] = &E;
pptest[2] = &F;
printf("Is F in pptest? %d\n", is_in(pptest, 2, &F, &ptreq));
return 0;
}
提供以下输出:
Is F in pptest? 0
即使&F
在pptest
之内。
这种方法的问题可能是什么?
3条答案
按热度按时间2q5ifsrm1#
类型
void
是一个不完整的类型,因此您可以在if语句中使用带有指针算法的表达式array + k
无效。
此外,您还需要将存储在数组中的对象的大小传递给函数,这些对象将在具有指针算法的表达式中使用。
使用您的方法时,该函数的声明应类似于标准C函数
bsearch
,如下所示只有返回类型必须从
void *
更改为int
。这就是函数的声明
该函数可按以下方式定义
一般而言,如果搜索的元素被分别视为小于、匹配或大于数组元素,则比较函数应返回小于、等于或大于零的整数。
在你的例子中,你有一个指针数组,可以指向任意对象,那么如果传递给函数的元素彼此相等,函数应该返回0,或者如果它们彼此不相等,函数应该返回一个正值。
注意传递的搜索元素
must have the type
Symbol**'。这是一个演示程序。
程序输出为
h9vpoimq2#
传递给
void*
参数的Symbol**
不会在另一端以数组形式出现,除非您将其强制转换为正确的类型。array + k
是无效的C,不会在符合标准的编译器上干净地编译。您不能在void*
上执行指针运算,也不能在不知道项大小的情况下循环访问它所指向的内容-在“这就是为什么qsort
把它作为参数的原因。正确编写的标准C函数可能如下所示:
gc0ot86w3#
正如其他人所指出的,这个问题是由于试图对
void*
执行加法而引起的,标准C中没有定义void*
。虽然其他答案通过传递项大小来避免这个问题,就像qsort()
的情况一样,但我设法通过将array
和k
分离为equals()
例程的不同参数来解决这个问题。然后在强制转换为适当的非void*
类型之后执行指针运算。