Reputation: 9063
I am imlementing a simple merge
function and I have got stuck, as the compiler gives me errors that I cannot explain. Here is my merge
function:
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;
}
}
}
And here is the error:
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
Can anyone help me? TIA.
Upvotes: 1
Views: 4955
Reputation: 184
Function prototype probably should look something like this:
void merge(void **a, int beg, int middle, int end, int (*cmp)(const void*, const void*));
Then you can access every array member by its index without any problem.
Note: The size of object pointed by void is unknown as previously mentioned by Ferdinand (therefore a + i can't be applied), but the size of void* is known therefore updating prototype in a such way does the trick.
Upvotes: 1
Reputation: 92211
The problem with void*
is that it is an address without a type. When you ask for a+i
you say "move i
elements further" without specifying what kind of elements. Is it one byte, one int, one car, one house, or one continent?
In C++ you don't have to use this kind of stuff, you can use templates and let the compiler figure out how to handle different types.
template<class T>
void merge(T* a, etc.
Upvotes: 1
Reputation: 35783
I can tell you about one of your errors. You're trying to do pointer arithmetic on a void*
. You see, when you add to a pointer, you are adding however many bytes there are in the type of the pointer. So, if you add to a void*
, the compiler can't know how many bytes to add, as void*
has no type. Therefore, if you want to do it at the byte level, cast to a char*
, or any other pointer level you want. If you want to do things byte by byte, you can take a void*
, but cast to char*
.
Upvotes: 0
Reputation: 67137
Pointer arithmetic is not possible with void*
, since void
has no size, and pointer arithmetic requires to compute memory addresses based on the size of the type.
If you expect beg
, middle
and end
to represent byte offsets, you should use char
pointers instead (one char
is one byte).
If you want to write a generic function, that works with any type, don't use void
pointers but templates:
template <typename t>
void merge(T *a, int beg, int middle, int end, int (*cmp)(const T*, const T*))
{
// ...
}
Upvotes: 4
Reputation: 1415
In first.push(a+i);
, you are trying to add an offset i
to a void *
pointer a
. This is illegal.
You can add offsets to any other "something pointer", because that something will be defined and will have a defined size in memory. Therefore adding an offset of 1 will mean moving forward of sizeof(something)
in memory. But void
has no defined size. Therefore you cannot use offsets with void *
pointers.
Upvotes: 1