繁体   English   中英

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

[英]How do you use the void pointer in C?

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

/* 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转换为应该返回的任何适当的东西?

void *通常意味着您只对数据的地址感兴趣,无论其类型如何,其中一些原因如下:

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

  • 这个类型在调用链中的某个函数中是已知的,就像qsort和大多数将参数传递给其他函数的函数一样。

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

使用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 ;
}

任何指针类型都可以分配给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* pointer参数,将数据重新解释为char数组,以执行逐字节复制。 要做到这一点,它不需要知道传递给它的tItem或任何其他数据对象的内部语义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM