简体   繁体   中英

Combining an int with a void*

I need to combine an int with a void*. I was thinking of doing it like :

long int lint = ((int)integer<<(sizeof(void*)*8)) | ((void*)ptr);

but according to my previous message , a long int won't suffice.

Can anyone suggest how to do this?

PS. Some people will ask why on earth I might want to do this. Well, I am developing a generic events system (dispatch/listen) that caters for countless different cases. I will post code when it's ready...

The only answer is to use struct

Don't try to be smarter than compiler. Don't perform premature optimization. Write simplest and clearest code and only after you see it too slow, perform low-level optimization

Struct are better here because:

  1. It is portable
  2. It safe
  3. It is c++ ideomatic.
  4. It is faster .

Let me bust your myths about comparing speed of long long and struct. As you know, all ways to optimize your code starts with profiling. Lets make simple program and measure comparing speed of vectors of long long and struct S :

#include <iostream>
#include <string>
#include <vector>
#include <windows.h>

struct S
{
    unsigned int a;
    void* b;

    bool operator==(const S& other)  const
    {
        return a == other.a && b == other.b;
    }
};

template <typename Iterator>
int count_eq(Iterator begin, Iterator end)
{
    int result = 0;
    for (Iterator i  = begin; i != end; ++i) {
        for (Iterator j  = i + 1; j != end; ++j) {
            result += *i == *j;
        }
    }
    return result;
}

template <typename Iterator>
void mesure(Iterator begin, Iterator end)
{
    long long t0 = GetTickCount();
    int res = count_eq(begin, end);
    long long t1 = GetTickCount();
    std::cout << "result: " << res <<"; Time: "<<(t1-t0)<<"\n";
}

int main()
{
    const unsigned int Size = 20000;
    std::vector<unsigned long long> l;
    for (int i = 0; i < Size; i++) {
        l.push_back(i% (Size/10));
    }

    std::vector<S> s;
    for (int j = 0; j < Size; j++) {
        S el;
        el.a = j% (Size/10);
        el.b = 0;
        s.push_back(el);
    }

    mesure(l.begin(), l.end());
    mesure(s.begin(), s.end()); 
}

Lets check results:

>g++ src.cpp -O3
>a
result: 90000; Time: 327
result: 90000; Time: 188

Yes, struct with custom operator == 1.5 times faster.

Hmm shouldn't it be something like:

long long res = ((long long)integer<<(sizeof(void*))) | ((long long)ptr);

Thit will still only work for 32 bit pointers and will not work for 64 bit. There is no built-in type that will fit such arithmetics.

you should use something like uint_least64_t , available from stdint.h , of course it cannot hold pointers from 64 bits systems, for that you would need to use a struct as many people have mentioned in the comments.

Though the way you are using the pointers seems weird, it looks like you don't even need to use void* for what you are doing, nevermind the fact that you could to the same thing with polymorphism (for the event system you described).

If you want a data structure that can store either an int or a void pointer, use a union . A union will be the size of the largest value it contains. You can do something like this:

typedef union {
    void *data,
    int *value
} myUnion_t;

myUnion_t storage;
int num = 10;

// if you want to store a void pointer
storage.data = &num;

// if you want to store an int
storage.value = num;

Keep in mind a union is not a struct and should only store one value at a time.

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