简体   繁体   中英

Void pointer values comparing C++

My actual question is it really possible to compare values contained in two void pointers, when you actually know that these values are the same type? For example int.

void compVoids(void *firstVal, void *secondVal){
     if (firstVal < secondVal){
          cout << "This will not make any sense as this will compare addresses, not values" << endl;
     }
} 

Actually I need to compare two void pointer values, while outside the function it is known that the type is int. I do not want to use comparison of int inside the function. So this will not work for me as well: if (*(int*)firstVal > *(int*)secondVal) Any suggestions? Thank you very much for help!

In order to compare the data pointed to by a void* , you must know what the type is. If you know what the type is, there is no need for a void* . If you want to write a function that can be used for multiple types, you use templates:

template<typename T>
bool compare(const T& firstVal, const T& secondVal)
{
    if (firstVal < secondVal)
    {
        // do something
    }
    return something;
}

To illustrate why attempting to compare void pointers blind is not feasible:

bool compare(void* firstVal, void* secondVal)
{
    if (*firstVal < *secondVal) // ERROR:  cannot dereference a void*
    {
        // do something
    }
    return something;
}

So, you need to know the size to compare, which means you either need to pass in a std::size_t parameter, or you need to know the type (and really, in order to pass in the std::size_t parameter, you have to know the type):

bool compare(void* firstVal, void* secondVal, std::size_t size)
{
    if (0 > memcmp(firstVal, secondVal, size))
    {
        // do something
    }
    return something;
}

int a = 5;
int b = 6;
bool test = compare(&a, &b, sizeof(int)); // you know the type!

This was required in C as templates did not exist. C++ has templates, which make this type of function declaration unnecessary and inferior (templates allow for enforcement of type safety - void pointers do not, as I'll show below).

The problem comes in when you do something (silly) like this:

int a = 5;
short b = 6;
bool test = compare(&a, &b, sizeof(int)); // DOH! this will try to compare memory outside the bounds of the size of b
bool test = compare(&a, &b, sizeof(short)); // DOH!  This will compare the first part of a with b.  Endianess will be an issue.

As you can see, by doing this, you lose all type safety and have a whole host of other issues you have to deal with.

You need to dereference them and cast, with

if (*(int*) firstVal < *(int*) secondVal)

Why do you not want to use the int comparison inside the function, if you know that the two values will be int and that you want to compare the int values that they're pointing to?


You mentioned a comparison function for comparing data on inserts; for a comparison function, I recommend this:

int
compareIntValues (void *first, void *second)
{
    return (*(int*) first - *(int*) second);
}

It follows the convention of negative if the first is smaller, 0 if they're equal, positive if the first is larger. Simply call this function when you want to compare the int data.

It is definitely possible, but since they are void pointers you must specify how much data is to be compared and how.

The memcmp function may be what you are looking for. It takes two void pointers and an argument for the number of bytes to be compared and returns a comparison. Some comparisons, however, are not contingent upon all of the data being equal. For example: comparing the direction of two vectors ignoring their length.

This question doesn't have a definite answer unless you specify how you want to compare the data.

yes. and in fact your code is correct if the type is unsigned int. casting int values to void pointer is often used even not recommended.

Also you could cast the pointers but you have to cast them directly to the int type:

if ((int)firstVal < (int)secondVal)

Note: no * at all.

You may have address model issues doing this though if you build 32 and 64 bits. Check the intptr_t type that you could use to avoid that.

if ((intptr_t)firstVal < (intptr_t)secondVal)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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