c - 类型不可知的所属函数

标签 c pointers search casting function-definition

我正在尝试构建一个函数来检查特定指针值是否存储在给定数组中。我试图使函数与类型无关,因此我决定采用用于实现 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 内。

这种方法可能存在什么问题?

最佳答案

类型void是一个不完整的类型。因此,您在 if 语句中使用表达式 array + k 和指针算术

 if(equals(array + k, pelement)) {

无效。

此外,您还需要将存储在数组中的对象的大小传递给函数,该数组将在带有指针算术的表达式中使用。

使用您的方法,该函数的声明方式应与标准 C 函数 bsearch 类似,如下所示

void *bsearch(const void *key, const void *base,
              size_t nmemb, size_t size,
              int (*compar)(const void *, const void *));

只需将返回类型从 void * 更改为 int

这就是你的函数的声明

int is_in( const void *pvalue, 
           const void *array, 
           size_t nmemb, 
           size_t size, 
           int cmp( const void *, const void *) );

该函数可以通过以下方式定义

int is_in( const void *pvalue, 
           const void *array, 
           size_t nmemb, 
           size_t size, 
           int cmp( const void *, const void *) )
{
    size_t i = 0;
    
    while ( i < nmemb && cmp( pvalue, ( const char * )array + i * size  )   != 0 ) i++;

    return i != nmemb;
}

一般来说,如果搜索的元素被认为小于、匹配或大于数组元素,则比较函数应返回小于、等于或大于零的整数。

在您的情况下,如果您有一个可以指向任意对象的指针数组,那么如果传递给函数的元素彼此相等,则函数应返回 0;如果传递给函数的元素彼此不相等,则函数应返回正值。

int ptreq( const void *ptr1, const void *ptr2 ) 
{
    return *( const Symbol ** )ptr1 != *( const Symbol ** )ptr2;
}

注意传递的搜索元素必须具有类型Symbol **`。

这是一个演示程序。

#include <stdio.h>

int is_in( const void *pvalue,
    const void *array,
    size_t nmemb,
    size_t size,
    int cmp( const void *, const void * ) )
{
    size_t i = 0;

    while (i < nmemb && cmp( pvalue, ( const char * )array + i * size ) != 0) i++;

    return i != nmemb;
}

int cmp_ptr( const void *ptr1, const void *ptr2 )
{
    return *( const int ** )ptr1 != *( const int ** )ptr2;
}

int main( void )
{
    int x, y, z;

    int * a[] = { &x, &y, &z };
    const size_t N = sizeof( a ) / sizeof( *a );

    int *pvalue = &y;

    printf( "&y is in the array = %s\n",
        is_in( &pvalue, a, N, sizeof( *a ), cmp_ptr ) ? "true" : "false" );

    int v;
    pvalue = &v;

    printf( "&v is in the array = %s\n",
        is_in( &pvalue, a, N, sizeof( *a ), cmp_ptr ) ? "true" : "false" );
}

程序输出为

&y is in the array = true
&v is in the array = false

关于c - 类型不可知的所属函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75234813/

相关文章:

Xcode 在输出日志中查找/搜索文本

c++ - Windows 中的网络文件传输

c - 指向二维指针数组的指针

c - 在文件中查找N个字母的单词

c - 函数声明和赋值数组问题

c - C中的内存分配

c# - 在 List<entity> 中搜索具有类属性匹配值的记录?

c - 二维字符串数组

c - 在 MacO 上启用 IPV6_RECVPKTINFO

c - qsort() 函数如何工作?