你如何在C中使用void指针?

时间:2014-08-08 23:48:20

标签: c++ c pointers

以下是一些函数声明,我无法理解如何完成。我已经扫描了网络以查看无效指针是什么,我理解它必须被转换为有用的东西(因为它只指向一些内存块),但我不知道这有助于完成这些声明。

/* type of comparison function that specifies a unique order.
   Returns 1 if pointer1 should come before,
   0 if equal to, or -1 if after pointer2. */
typedef int (*compare_function) (const void* pointer1, const void* pointer2);

/* get the data object */
void* get_obj(const void* item_pointer);

还有更多这样的功能,但我想如果我明白如何做到这两个我应该保持良好状态。例如,对于第二个函数,我们如何将item_pointer转换为应该返回的任何适当的东西?

3 个答案:

答案 0 :(得分:9)

void *通常意味着您只对数据的地址感兴趣而不管其类型,原因如下:

  • 这个void *指向的数据的内部表示是隐藏的,你不应该直接访问数据information hiding,你的函数2就是这种情况的一个例子。

  • 调用链中的某个函数知道类型,例如qsort和大多数将参数传递给其他函数的函数。

  • 该类型不是必需的,因为指针所指向的数据将被处理为不同的类型,例如memcpy可以将数据作为字节处理unsigned char *

答案 1 :(得分:1)

使用quicksort在C中排序使用void指针,以便我们可以对数组中的任何数据进行排序。如果参数b在参数a之前,之后或相同,则sort函数必须返回-1,+ 1或0

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

int sort_order( const void *, const void *);

int main(void)
{
  int i;
  char alfa[6] = { ’C’, ’E’, ’A’, ’D’, ’F’, ’B’ }; 
  qsort( (char*)alfa, 6, sizeof(char), sort_order); 
  for (i=0 ; i<5 ; i++)  // now in order?
     printf("\nchar %d = %c",i, alfa[i]);
  printf("\n");
  system("PAUSE");
  return 0;
}

int sort_order( const void* a, const void* b)
{
  if      ( *((char*)a) < *((char*)b) )     return -1 ;
  else if ( *((char*)a) > *((char*)b) )     return  1 ;
  else                                      return  0 ;
}

然后您可以对自己的数据类型进行排序:

typedef struct {   float left;   float right;} ears;
typedef struct{  char name[13];  int weight;  ears eararea;} monkey;    

monkey* Index[4];

for(i=0;i<4;i++)   
    Index[i]= (monkey* )malloc(sizeof(monkey));     

qsort((void* ) Index, 4, sizeof(monkey* ), sort_order);

// Sorted by weight    
int sort_order( const void* a, const void* b) {   
    if((**((monkey** )a)).weight < (**((monkey** )b)).weight) return -1 ;   
    else if ((**((monkey** )a)).weight > (**((monkey** )b)).weight ) return  1 ;
    else return  0 ;
}

完成程序

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

typedef struct {
    float left;
    float right;
} ears;

typedef struct {
    char name[13];
    int weight;
    ears eararea;
} monkey;

int sort_monkeys( const void *, const void *);

int main(void)
{   monkey* monkeys[4];
    int i;
    for(i=0; i<4; i++) {
        monkeys[i]= (monkey* )malloc(sizeof(monkey));
        monkeys[i]->weight=i*10;
        if (i==2)
            monkeys[i]->weight=1;
    }
    for (i=0 ; i<4; i++)
        printf("\nchar %d = %i",i, monkeys[i]->weight);

    qsort((void* ) monkeys, 4, sizeof(monkey* ), sort_monkeys);

    for (i=0 ; i<4; i++)  // now in order?
        printf("\nmonkey %d = %i",i, monkeys[i]->weight);
    return 0;
}

// Sorted by weight
int sort_monkeys( const void* a, const void* b) {
    if((**((monkey** )a)).weight < (**((monkey** )b)).weight) return -1 ;
    else if ((**((monkey** )a)).weight > (**((monkey** )b)).weight ) return  1 ;
    else return  0 ;
}

答案 2 :(得分:0)

任何指针类型都可以分配给void*,这在函数不需要知道类型或者通过其他方式传达类型信息的情况下很有用。这允许您只编写一个函数来处理任何指针类型,而不是每个数据类型的单独函数。

虽然你不能取消引用void*你可以将它转换为任何类型并取消引用它 - 它的语义 - 即它是否有意义,取决于代码而不是强制字节编译器。

泛型函数通常不会对某些数据块的内容感兴趣,只对其地址和通常大小感兴趣。

举个简单的例子:

void memcopy( void* to, void* from, int length )
{
    char* source = (char*)from ;
    char* dest = (char*)to ;
    int i ;

    for( i = 0; i < lengt; i++ )
    {
        dest[i] = source[i] ;
    }
}

int main()
{
    typedef struct
    {
        int x ;
        int y ;

    } tItem

    tItem AllItems[256] = {0} ;
    tItem AllItemsCopy[256] ;

    memcopy( AllItemsCopy, AllItems, sizeof(AllItems) ) ;
}

看到memcopy()不需要知道tItem是什么来复制它们的数组,它只需要知道数组中的地址和大小(以字节为单位)。它会转换void*指针参数,将数据重新解释为char数组,以执行逐字节复制。为此,它不需要知道tItem的内部语义或传递给它的任何其他数据对象。