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

void function(void *i, void *j);

struct mystruct {
    int a;
    int b;
} ;

int main()
{

    int a = 50;

    struct mystruct s ;
    s.a = 100;
    s.b = 200;
    function(&a, &s);


}


void function(void *i, void *j)
{
    printf("Integer is %d\n", *i);
    printf("Struct member 1 is %d\n", j->a);
    printf("Struct member 2 is %d\n", j->b);


}

我上面的代码。在编译时,我得到以下错误,我明白我需要做些什么来修复它们。

voidstartest.c: In function function:
voidstartest.c:27: warning: dereferencing  void *  pointer
voidstartest.c:27: error: invalid use of void expression
voidstartest.c:28: warning: dereferencing  void *  pointer
voidstartest.c:28: error: request for member  a  in something not a structure or union
voidstartest.c:29: warning: dereferencing  void *  pointer
voidstartest.c:29: error: request for member  b  in something not a structure or union

这是我需要做的来修复错误:

printf("Integer is %d\n", *(int*)i);

printf("Struct member 1 is %d\n", ((struct mystruct *)j)->a);

printf("Struct member 2 is %d\n", ((struct mystruct *)j)->b);

问题:

  1. 如果我必须按照上面描述的方式修复错误,这是否意味着我必须提前知道要发送给函数的指针类型?我觉得这是一个非常严格的要求。不是吗?

  2. 一些库函数也有作为 void * 的形式参数(如 qsort)。他们的实现如何知道指针的正确类型是什么,以便他们可以取消引用它以处理实际数据(它指向)?

4

4 回答 4

5
  1. 是的。这意味着您不能以与类型无关的方式编写函数,因此需要重新考虑您的设计。使用时void*通常会编写一个模板函数,并要求用户提供函数指针,指向知道类型并执行基本操作的函数。

  2. 他们的实施没有。他们还以我上面描述的相同方式要求您提供函数指针或大小参数。

于 2013-05-16T15:26:04.370 回答
5

一些库函数也有作为 void * 的形式参数(如 qsort)。他们的实现如何知道指针的正确类型是什么,以便他们可以取消引用它以处理实际数据(它指向)?

因为你还提供了一个比较函数,它接受两个 void 指针并返回比较的结果:

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

在该函数中,您可以将 void 指针转换为指向数组元素实际类型的指针,然后执行您想要的任何操作

int compare_your_structs(const void *first, const void *second)
{
    const struct mystruct *first_struct = (struct mystruct *)first;
    const struct mystruct *second_struct = (struct mystruct *)second;
    /* sort by the "a" field only */
    return first_struct->a - second_struct->a;
}
于 2013-05-16T15:28:32.473 回答
1

C 是静态类型的。AC程序一般不能在运行时推断出指针所指向的对象的类型,无论是void指针还是其他类型的指针。它相信您不会滥用指针,将它们指向与它们自己声明的类型不同的类型的对象。动态类型语言通常会在提供此类额外功能时产生开销。

qsort不需要知道其 void 指针参数所指向的对象的类型。它知道它们的大小,并提供了一个比较函数,预计该函数是为了比较相关类型的对象而编写的。

于 2013-05-16T15:29:53.177 回答
0

库函数可以处理void*许多不同的方式。例如,qsort要求用户提供为特定类型编写的函数指针。这样,用户只需要知道类型,但qsort无需此信息即可工作。

其他功能,如memcpyvoid*为方便起见。实际上,由于memcpy是按字节复制,char*因此它将参数转换为,以便可以在字节级别上工作。

也可以编写一个类似的函数,printf该函数接受一个标识其参数类型的字符串。类似地,va_arg 宏(用于处理可变参数)需要一个类型参数,例如va_arg(list, int). 虽然printf并且va_arg不与(我认为?)一起工作,但由于 a是无类型void*的,他们面临同样的问题。va_list所以这些概念也可以用于在void*.

于 2013-05-16T15:34:14.067 回答