我正在推理一个简单的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。
答案 0 :(得分:4)
void*
无法使用指针运算,因为void
没有大小,指针算法需要根据类型的大小计算内存地址。
如果您希望beg
,middle
和end
代表字节偏移,则应使用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*
。