如何使用void *

时间:2012-06-28 15:09:25

标签: c++ void-pointers

我正在推理一个简单的merge函数而且我遇到了困难,因为编译器给了我无法解释的错误。这是我的merge函数:

void merge(void *a, int beg, int middle, int end, int (*cmp)(const void*, const void*
{
  std::stack<void*> first;
  std::stack<void*> second;

  for(int i = beg; i < middle; i++) {
   first.push(a+i);
  }
  for(int i = middle; i < end; i++) {
    second.push(a+i);
  }

  for(int i = beg; i < end; i++) {
    if(first.empty()) {
      void *tmp = second.top();
      second.pop();
      a+i = tmp;
    } else if(second.empty()) {
      void *tmp = first.top();
      first.pop();
      a+i = tmp;
    } else if(cmp(first.top(), second.top())) {
      void *tmp = first.top();
      first.pop();
      a+i = tmp;
    } else {
      void *tmp = second.top();
      second.pop();
      a+i = tmp;
    }
  }
}

这是错误:

sort.h: In function `void merge(void*, int, int, int, int (*)(const void*, const void*))':
sort.h:9: error: pointer of type `void *' used in arithmetic
sort.h:12: error: pointer of type `void *' used in arithmetic
sort.h:19: error: pointer of type `void *' used in arithmetic
sort.h:19: error: non-lvalue in assignment
sort.h:23: error: pointer of type `void *' used in arithmetic
sort.h:23: error: non-lvalue in assignment
sort.h:27: error: pointer of type `void *' used in arithmetic
sort.h:27: error: non-lvalue in assignment
sort.h:31: error: pointer of type `void *' used in arithmetic
sort.h:31: error: non-lvalue in assignment

任何人都可以帮助我吗? TIA。

5 个答案:

答案 0 :(得分:4)

void*无法使用指针运算,因为void没有大小,指针算法需要根据类型的大小计算内存地址。

如果您希望begmiddleend代表字节偏移,则应使用char指针代替char是一个字节)。

如果你想编写适用于任何类型的泛型函数,请不要使用void指针而是使用模板:

template <typename t>
void merge(T *a, int beg, int middle, int end, int (*cmp)(const T*, const T*))
{
    // ...
}

答案 1 :(得分:1)

first.push(a+i);中,您尝试向i指针void *添加偏移量a。这是非法的。

您可以将偏移量添加到任何其他“某事物指针”,因为某些内容将被定义并且在内存中将具有已定义的大小。因此,添加偏移量1意味着在内存中向前移sizeof(something)。但是void没有定义的大小。因此,您不能使用带有void *指针的偏移量。

答案 2 :(得分:1)

void*的问题在于它是一个没有类型的地址。当您要求a+i时,您会说“进一步移动i元素”而不指定哪种元素。它是一个字节,一个整数,一个汽车,一个房子,还是一个大陆?

在C ++中你不必使用这种东西,你可以使用模板让编译器弄清楚如何处理不同的类型。

template<class T>
void merge(T* a, etc.

答案 3 :(得分:1)

函数原型可能应该是这样的:

void merge(void **a, int beg, int middle, int end, int (*cmp)(const void*, const void*));

然后你可以通过索引访问每个数组成员而没有任何问题。

注意:由void指出的对象的大小是未知的,如前面Ferdinand所提到的(因此无法应用+ i),但是void *的大小是已知的,因此以这种方式更新原型就可以了。

答案 4 :(得分:0)

我可以告诉你一个错误。你试图在void*上做指针算术。您会看到,当您添加到指针时,您将添加指针类型中的许多字节。因此,如果添加到void*,编译器无法知道要添加多少字节,因为void*没有类型。因此,如果要在字节级别执行此操作,请转换为char*或任何其他所需的指针级别。如果您想逐字节地执行操作,可以使用void*,但转换为char*